26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
136 for(
int x = 0; x < 4; x++)
145 for(
int x = 0; x < 4; x++)
154 for(
int x = 0; x < 4; x++)
159 for(
int x = 0; x < 4; x++)
163 for(
int x = 0; x < 3; x++)
201 for(
int x = 0; x < 4; x++)
262 throw Exception(
"Error in attempting to delete FrontCodePtr");
266 for(
int x = 0; x < 4; x++)
270 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
275 for(
int x = 0; x < 4; x++)
279 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
308 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
374 bool TempDerail =
false;
420 else if((NextElementPosition > -1) && (NextEntryPos > -1))
491 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
501 for(
int x = 0; x < 4; x++)
508 for(
int x = 0; x < 4; x++)
769 int LockedVectorNumber;
899 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
900 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
901 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
902 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
903 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
904 "of a shortage of on train crew"};
911 if(DwellTime < TDateTime(30.0 / 86400))
913 DwellTime = TDateTime(30.0 / 86400);
915 int randval = random(10000);
920 if(randval < Utilities->MinorDelayCutoff)
927 if(randval < Utilities->ModerateDelayCutoff)
934 if(randval < Utilities->MajorDelayCutoff)
949 if(
NewDelay <
double(DwellTime) * 1440)
955 NewDelay -= double(DwellTime) * 1440;
1016 int randval2 = rand() % 24;
1017 AnsiString Reason = ReasonArray[randval2];
1020 " minutes because " + Reason);
1022 " minutes because " + Reason);
1028 " minutes because of a minor problem");
1030 " minutes because of a minor problem");
1182 if(BufferLocation ==
"")
1187 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1249 int NextElementPosition, NextEntryPos;
1273 NextElementPosition = -1;
1276 if((NextElementPosition > -1) && (NextEntryPos > -1))
1421 AnsiString StationName;
1432 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1442 if((NextElementPosition > -1) && (NextEntryPos > -1))
1590 if(TIFEntryPos == 0)
1627 if(NextElementPosition > -1)
1664 AnsiString Loc =
"";
1665 bool LocNamed =
false;
1694 Loc =
"outside railway";
1726 NextElementPosition = -1;
1737 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1755 if((NextElementPosition > -1) && (NextEntryPos > -1))
1793 FirstPair.second).
GetELink() == TempELink))
1798 SecondPair.second).
GetELink() == TempELink))
1812 FirstPair.second).
GetELink() == TempELink))
1817 SecondPair.second).
GetELink() == TempELink))
1831 FirstPair.second).
GetELink() == TempELink))
1836 SecondPair.second).
GetELink() == TempELink))
1866 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1869 int NewLastElement = 0, NewLastExitPos = 0;
1887 if(NewLastElement == -1)
1893 if(NewLastExitPos == -1)
1897 LastElement = NewLastElement;
1898 LastExitPos = NewLastExitPos;
1901 if(CumDistance < 1200)
1907 int FirstDistance = 0;
1908 if(CumDistance >= 1200)
1910 FirstDistance = 100;
1914 FirstDistance = 1200 - CumDistance;
1916 if(FirstDistance < 100)
1918 FirstDistance = 100;
1944 if(VectorIT->RouteNumber == RouteNumber)
1981 " failed when changing aspect.\nTrains can only pass under signaller control.");
2015 LockedVectorNumber)))
2174 for(
int x = 0; x < 4; x++)
2181 for(
int x = 0; x < 4; x++)
2207 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2212 if(OtherTrainEntryPos == -1)
2214 throw Exception(
"Error - OtherTrainEntryPos not set");
2233 int OtherTrainID = -1;
2234 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2325 bool StopRequired =
false;
2340 int NextElementEntryPos = -1;
2341 int NextElementExitPos = -1;
2342 bool TrainOnNextElement =
false;
2343 bool StopSignalAtNextElement =
false;
2344 if(ForwardConnection)
2352 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2354 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2410 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2623 if(Code.Length() != 4)
2627 for(
int x = 1; x < 5; x++)
2634 for(
int x = 0; x < 4; x++)
2797 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2810 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2825 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2834 TRect SourceRect, DestRect;
2836 DestRect.init(0, 0, 8, 8);
2839 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2841 TempGraphic->PixelFormat = pf8bit;
2842 TempGraphic->Width = 16;
2843 TempGraphic->Height = 16;
2849 TempGraphic->Transparent =
true;
2853 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2854 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2860 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2868 else if(TempElement.
SpeedTag == 89)
2872 else if(TempElement.
SpeedTag == 90)
2876 else if(TempElement.
SpeedTag == 91)
2880 else if(TempElement.
SpeedTag == 92)
2884 else if(TempElement.
SpeedTag == 93)
2888 else if(TempElement.
SpeedTag == 94)
2892 else if(TempElement.
SpeedTag == 95)
2896 TempGraphic->Transparent =
true;
2900 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2901 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2903 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2910 for(
int x = 0; x < 40; x++)
2925 TempGraphic->Transparent =
true;
2929 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2930 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2932 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2946 TempGraphic->Transparent =
true;
2950 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2951 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2955 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2958 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2963 TempGraphic->Transparent =
true;
2967 int BDVectorPos = -1;
2976 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2981 TempGraphic->Transparent =
true;
2985 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2986 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2988 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2994 TempGraphic->Transparent =
true;
2998 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2999 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3001 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3267 throw Exception(
"Error, same train on two different bridge tracks");
3313 AnsiString(EntryPos) +
"," +
HeadCode);
3330 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3349 AnsiString(EntryPos) +
"," +
HeadCode);
3358 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3391 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3392 int LockedVectorNumber;
3405 TRect SourceRect, DestRect;
3406 DestRect.init(0, 0, 8, 8);
3413 int FirstELink, SecondELink = -1;
3416 if(RoutePair2.first > -1)
3425 if(SecondELink == -1)
3427 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3432 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3442 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3443 DestGraphic->PixelFormat = pf8bit;
3444 DestGraphic->Width = 8;
3445 DestGraphic->Height = 8;
3446 DestGraphic->Transparent =
true;
3449 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3458 PrefDirElement, LockedVectorNumber))
3473 if(ElementEntryPos > 1)
3495 AnsiString(EntryPos) +
"," +
HeadCode);
3497 bool WrongRoute =
false;
3523 int LinkNumber = TrackElement.
Link[EntryPos];
3524 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3529 bool LogActionErrorCalled =
false;
3539 LogActionErrorCalled =
true;
3556 else if(LinkNumber == 3)
3564 LogActionErrorCalled =
true;
3581 else if(LinkNumber == 7)
3589 LogActionErrorCalled =
true;
3606 else if(LinkNumber == 9)
3614 LogActionErrorCalled =
true;
3646 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3651 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3661 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3666 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3675 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3696 bool ColourError =
false, ColourError2 =
false;
3701 ColourError2 =
true;
3703 for(
int x = 0; x < 4; x++)
3708 ColourError2 =
true;
3714 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3718 for(
int x = 0; x < 4; x++)
3805 AnsiString(EntryPos) +
"," +
HeadCode);
3806 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3807 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3808 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3809 TrainInFrontInSignallerModeFlag =
false;
3810 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3811 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3812 bool SignallerStopRequired =
false;
3826 if(CurrentTrackVectorPosition > -1)
3830 if((EntryPos == 0) || (EntryPos == 2))
3843 else if(EntryPos == 1)
3867 EntryHalfLength = CurrentElementHalfLength;
3872 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3876 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3924 FrontElementMaxSpeed = LimitingSpeed;
3960 double ExitSpeedAtMaxBraking;
3965 ExitSpeedAtMaxBraking = 0;
3975 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3977 SpeedToUse = ExitSpeedAtMaxBraking;
3981 SpeedToUse = LimitingSpeed;
3996 RedSignalFlag =
false;
3997 BuffersFlag =
false;
3998 StationFlag =
false;
3999 BuffersOrContinuationNowFlag =
false;
4000 ContinuationNextFlag =
false;
4003 CumulativeLength += (2 * CurrentElementHalfLength);
4006 SignallerStopRequired =
true;
4028 bool StopRequired =
false;
4044 StationFlag =
false;
4050 BuffersOrContinuationNowFlag =
true;
4052 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4056 if((EntryPos == 0) || (EntryPos == 2))
4078 if(NextTrackVectorPosition > -1)
4083 if((NextEntryPos == 0) || (NextEntryPos == 2))
4096 else if(NextEntryPos == 1)
4109 if(NextEntryPos > 1)
4123 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4135 RedSignalFlag =
true;
4156 TrainInFrontInSignallerModeFlag =
true;
4181 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4193 double MaxHalfSpeed;
4197 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4199 MaxHalfSpeed = FrontElementMaxSpeed;
4203 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4211 bool HalfSpeedLimited =
false;
4215 HalfSpeedLimited =
true;
4245 if(HalfSpeedLimited)
4270 if(SignallerStopRequired)
4286 int TempMaxExitSpeed;
4289 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4291 MaxExitSpeedAtHalfBraking = 0;
4295 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4299 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4301 TempMaxExitSpeed = FrontElementMaxSpeed;
4305 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4317 if(ExitSpeedHalfSquared < 10)
4327 if(ExitSpeedFullSquared < 10)
4399 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4400 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4424 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4425 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4435 if(!BuffersOrContinuationNowFlag)
4437 if(NextSpeedLimit < LimitingSpeed)
4439 LimitingSpeed = NextSpeedLimit;
4443 int TempMaxExitSpeed;
4447 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4449 MaxExitSpeedAtHalfBraking = 0;
4453 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4455 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4457 TempMaxExitSpeed = FrontElementMaxSpeed;
4461 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4472 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4485 if(!BuffersOrContinuationNowFlag)
4487 CurrentTrackVectorPosition = NextTrackVectorPosition;
4488 EntryPos = NextEntryPos;
4489 CurrentElementHalfLength = NextElementHalfLength;
4492 ContinuationNextFlag =
true;
4496 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4516 if(ExitSpeedHalfSquared < 10)
4526 if(ExitSpeedFullSquared < 10)
4589 double DeltaExitTimeToMaxInSecs;
4590 double DistanceToMax;
4599 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4601 DistanceToMax = EntryHalfLength;
4604 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4605 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4622 double DeltaExitTimeToMaxInSecs;
4623 double DistanceToMax;
4632 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4634 DistanceToMax = EntryHalfLength / 2;
4637 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4638 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4649 if(ExitSpeedHalfSquared < 10)
4659 if(ExitSpeedFullSquared < 10)
4678 if((EntryPos == 0) || (EntryPos == 2))
4700 if(NextTrackVectorPosition > -1)
4702 int NextElementLength;
4703 if(NextEntryPos > 1)
4711 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4907 int ElementCount = 0;
4915 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4973 if((EntryPos == 0) || (EntryPos == 2))
4995 CurrentTrackVectorPosition = NextTrackVectorPosition;
4996 EntryPos = NextEntryPos;
4998 if(ElementCount > 1000)
5026 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5051 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5052 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5053 int RouteStartPosition;
5055 int PlatformPosition;
5057 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5073 if(Distance > (4000 + LeadElementDistance))
5096 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5099 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5145 if(!PlatformFoundFlag)
5147 PlatformPosition = CurrentTrackVectorPosition;
5150 PlatformFoundFlag =
true;
5166 if((EntryPos == 0) || (EntryPos == 2))
5210 if(ElementNumber < 2)
5212 SkipRouteCheck =
true;
5216 SkipRouteCheck =
false;
5218 if(ElementNumber == 1)
5220 RouteStartPosition = CurrentTrackVectorPosition;
5230 if(ElementNumber > 1)
5234 RouteOrPartRouteSet =
true;
5238 RouteOrPartRouteSet =
false;
5241 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5248 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5249 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5261 Distance += CurrentTrackElement.
Length01;
5265 Distance += CurrentTrackElement.
Length23;
5267 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5268 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5269 CurrentTrackVectorPosition = NextTrackVectorPosition;
5270 EntryPos = NextEntryPos;
5307 return(RepeatHeadCode);
5329 bool FrontValid =
false, RearValid =
false;
5330 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5334 TrainToBeJoinedBy = NULL;
5348 int TrainToBeJoinedByID = -1;
5369 if((TrainToBeJoinedByID < 0) && RearValid)
5388 if(TrainToBeJoinedByID < 0)
5390 TrainToBeJoinedBy = NULL;
5395 if(!TrainToBeJoinedBy->
Stopped())
5397 TrainToBeJoinedBy = NULL;
5407 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5408 TDateTime TimetableNonRepeatTime,
bool Warning)
5444 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5445 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5446 int IntMinsLate = 0;
5447 bool TTEvent =
false;
5452 ActionLog =
" arrived at ";
5462 ActionLog =
" terminated at ";
5468 ActionLog =
" departed from ";
5471 if(ActionType ==
Pass)
5473 ActionLog =
" passed ";
5478 ActionLog =
" created at ";
5480 if(ActionType ==
Enter)
5482 ActionLog =
" entered railway at ";
5486 ActionLog =
" changed its description to '" +
Description +
"' at ";
5489 if(ActionType ==
Leave)
5491 ActionLog =
" left railway at ";
5496 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5501 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5506 ActionLog =
" joined by ";
5511 ActionLog =
" changed direction at ";
5516 ActionLog =
" became new service ";
5521 ActionLog =
" taken under signaller control at ";
5525 ActionLog =
" restored to timetable control at ";
5531 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5535 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5539 ActionLog =
" REMOVED FROM RAILWAY at ";
5544 ActionLog =
" received signaller authority to proceed";
5548 ActionLog =
" received signaller authority to step forward";
5552 ActionLog =
" changed direction under signaller control at ";
5556 ActionLog =
" received signaller authority to pass stop signal";
5560 ActionLog =
" received signaller instruction to stop";
5564 ActionLog =
" stopped on signaller instruction ";
5568 ActionLog =
" joined under signaller control by ";
5572 ActionLog =
" suffered an onboard power failure at ";
5576 ActionLog =
" failure repaired at ";
5580 ActionLog =
" left railway under signaller control at ";
5582 if(OtherHeadCode !=
"")
5584 OtherHeadCode +=
" at ";
5616 bool TimePerformance =
true;
5624 TimePerformance =
false;
5628 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5630 if(ActionType ==
Pass)
5644 IntMinsLate = int(ceil(MinsLate));
5648 IntMinsLate = int(floor(MinsLate));
5650 if(IntMinsLate == 0)
5652 PerfLog =
" on time";
5654 else if(IntMinsLate == 1)
5656 PerfLog =
" 1 minute late";
5658 else if(IntMinsLate == -1)
5660 PerfLog =
" 1 minute early";
5662 else if(IntMinsLate > 1)
5664 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5666 else if(IntMinsLate < -1)
5668 int PosIntMinsLate = -IntMinsLate;
5669 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5671 if(LocationName.Pos(
'-') > 0)
5673 PerfLog =
"," + PerfLog;
5686 if(ReminderBaseLog !=
"")
5689 ReminderBaseLog =
"";
5693 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5697 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5702 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5708 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5712 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5717 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5723 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5727 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5732 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5738 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5742 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5761 AnsiString LocName =
"";
5832 if(LocationName ==
"")
5836 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
5837 int FrontTrainRearPos, FrontTrainFrontPos;
5840 if(LocationName ==
"")
5842 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5846 bool TemporaryDelay =
false;
5848 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
5872 AnsiString SplittingTrainDescription =
Description;
5879 for(
int x = 0; x < 4; x++)
5899 double NewTrainPowerAtRail;
5905 NewTrainMass =
Mass * double(MassPercent)/100.0;
5907 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5908 if(NewTrainPowerAtRail == 0)
5910 NewTrainPowerAtRail = 0.08;
5918 NewTrainMass =
Mass;
5946 if(!SplitTrainExplicitDescription)
5991 if(LocationName ==
"")
5995 int RearTrainRearPos, RearTrainFrontPos;
5996 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
5999 if(LocationName ==
"")
6001 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6005 bool TemporaryDelay =
false;
6007 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6031 AnsiString SplittingTrainDescription =
Description;
6038 for(
int x = 0; x < 4; x++)
6058 double NewTrainPowerAtRail;
6064 NewTrainMass =
Mass * double(MassPercent)/100.0;
6066 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6067 if(NewTrainPowerAtRail == 0)
6069 NewTrainPowerAtRail = 0.08;
6077 NewTrainMass =
Mass;
6105 if(!SplitTrainExplicitDescription)
6196 TTrain *TrainToBeJoinedBy;
6229 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6231 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6295 int RouteNumber = -1;
6300 int CorrectRouteID = OR.
RouteID;
6306 bool FirstPass =
true;
6311 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6445 for(
int x = 0; x < IncNum; x++)
6478 else if(Ptr->
Command ==
"jbo")
6483 else if(Ptr->
Command ==
"dsc")
6494 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6500 bool IncludeFER =
false;
6508 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6513 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6524 else if(Ptr->
Command ==
"Fjo")
6530 else if(Ptr->
Command ==
"Frh")
6540 else if(Ptr->
Command ==
"Frh-sh")
6591 else if(Ptr->
Command ==
"jbo")
6596 else if(Ptr->
Command ==
"dsc")
6601 else if(Ptr->
Command ==
"cdt")
6609 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7031 int RouteNumber = -1;
7036 int CorrectRouteID = OR.
RouteID;
7042 bool FirstPass =
true;
7047 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7075 ",FloatingLabelNextString" +
"," +
HeadCode);
7076 AnsiString RetStr =
"", LocationName =
"";
7079 if(ActionTime == TDateTime(-1))
7083 if(ActionTime == TDateTime(-1))
7089 if(ActionTime != TDateTime(-1))
7097 throw Exception(
"Error - start entry in FloatingLabelNextString");
7141 else if(Ptr->
Command ==
"Fns")
7147 else if(Ptr->
Command ==
"F-nshs")
7178 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7180 else if(Ptr->
Command ==
"Frh")
7182 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7184 else if(Ptr->
Command ==
"Fer")
7186 AnsiString AllowedExits =
"";
7189 else if(Ptr->
Command ==
"Fjo")
7194 else if(Ptr->
Command ==
"jbo")
7199 else if(Ptr->
Command ==
"fsp")
7204 else if(Ptr->
Command ==
"rsp")
7209 else if(Ptr->
Command ==
"cdt")
7213 else if(Ptr->
Command ==
"dsc")
7222 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7266 else if(Ptr->
Command ==
"Fns")
7272 else if(Ptr->
Command ==
"F-nshs")
7303 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7305 else if(Ptr->
Command ==
"Frh")
7307 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7309 else if(Ptr->
Command ==
"Fer")
7311 AnsiString AllowedExits =
"";
7314 else if(Ptr->
Command ==
"Fjo")
7319 else if(Ptr->
Command ==
"jbo")
7324 else if(Ptr->
Command ==
"fsp")
7329 else if(Ptr->
Command ==
"rsp")
7334 else if(Ptr->
Command ==
"cdt")
7338 else if(Ptr->
Command ==
"dsc")
7347 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7391 else if(Ptr->
Command ==
"Fns")
7397 else if(Ptr->
Command ==
"F-nshs")
7428 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7430 else if(Ptr->
Command ==
"Frh")
7432 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7434 else if(Ptr->
Command ==
"Fer")
7436 AnsiString AllowedExits =
"";
7439 else if(Ptr->
Command ==
"Fjo")
7444 else if(Ptr->
Command ==
"jbo")
7449 else if(Ptr->
Command ==
"fsp")
7454 else if(Ptr->
Command ==
"rsp")
7459 else if(Ptr->
Command ==
"cdt")
7463 else if(Ptr->
Command ==
"dsc")
7607 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7608 AnsiString DepTime =
"", EventTime =
"";
7609 bool CDTFlag =
false;
7611 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7612 AnsiString TowardsLocation =
"";
7615 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7617 TowardsLocation = AVI->LocationName;
7619 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7628 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7635 if(AVI->Command ==
"cdt")
7640 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7655 RetStr +=
"\nNew service splits at approx. " + EventTime;
7659 if(AVI->Command ==
"jbo")
7678 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7693 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7697 if(AVI->Command ==
"Fjo")
7716 if(AVI->Command ==
"Frh")
7718 RetStr +=
"\nNew service finishes and remains at the location.";
7722 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7729 if(TowardsLocation !=
"")
7731 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7735 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7740 if(TowardsLocation !=
"")
7742 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7746 RetStr +=
"\nNew service departs at " + DepTime;
7755 if(TowardsLocation !=
"")
7757 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7761 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7766 if(TowardsLocation !=
"")
7768 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7772 RetStr +=
"\nNew service departs at approx. " + DepTime;
7789 if(TowardsLocation !=
"")
7791 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7795 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7800 if(TowardsLocation !=
"")
7802 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7806 RetStr +=
"\nNew service departs at approx. " + DepTime;
7825 ",FloatingTimetableString" +
"," +
HeadCode);
7826 AnsiString RetStr =
"", PartStr =
"";
7828 bool SkipDep =
false, SkipDepActedOn =
false;
7834 throw Exception(
"Error - start entry in FloatingTimetableString");
7837 bool FirstPass =
true;
7850 AnsiString TrainLoc =
"";
7896 AnsiString TrainLoc =
"";
7936 else if(Ptr->
Command ==
"Fns")
7942 else if(Ptr->
Command ==
"F-nshs")
7975 else if(Ptr->
Command ==
"Frh")
7979 else if(Ptr->
Command ==
"Fer")
7981 AnsiString AllowedExits =
"";
7984 else if(Ptr->
Command ==
"Fjo")
7989 else if(Ptr->
Command ==
"jbo")
7994 else if(Ptr->
Command ==
"fsp")
8004 PartStr+=
", split mass%-Power% = 50-50";
8007 else if(Ptr->
Command ==
"rsp")
8017 PartStr+=
", split mass%-Power% = 50-50";
8020 else if(Ptr->
Command ==
"cdt")
8024 else if(Ptr->
Command ==
"dsc")
8030 RetStr = RetStr +
'\n' + PartStr;
8044 SkipDepActedOn =
true;
8055 RetStr =
"Timetable finished";
8059 RetStr =
"No timetable";
8063 return(
"Timetable:\n" + RetStr);
8216 bool ForwardHeadCode;
8220 ForwardHeadCode =
true;
8225 ForwardHeadCode =
false;
8368 if(ColourNumber == 0)
8372 else if(ColourNumber == 1)
8376 else if(ColourNumber == 2)
8380 else if(ColourNumber == 3)
8384 else if(ColourNumber == 4)
8388 else if(ColourNumber == 5)
8392 else if(ColourNumber == 6)
8396 else if(ColourNumber == 7)
8400 else if(ColourNumber == 8)
8404 else if(ColourNumber == 9)
8408 else if(ColourNumber == 10)
8412 else if(ColourNumber == 11)
8416 else if(ColourNumber == 12)
8420 else if(ColourNumber == 13)
8424 else if(ColourNumber == 14)
8436 for(
int x = 0; x < 4; x++)
8443 for(
int x = 0; x < 4; x++)
8528 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8531 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8532 bool GiveMessagesFalse =
false;
8533 bool CheckLocationsExistInRailwayTrue =
true;
8540 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8543 if(Marker[6] ==
'1')
9008 bool HideFlashingTrain =
true;
9011 Graphics::TBitmap *SmallTrainBitmap;
9052 HideFlashingTrain =
false;
9057 HideFlashingTrain =
false;
9062 HideFlashingTrain =
false;
9067 HideFlashingTrain =
false;
9072 HideFlashingTrain =
false;
9076 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9080 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9104 for(
int y = 0; y < 3; y++)
9108 bool FoundFlag =
false;
9119 if(IMPair.first != IMPair.second)
9146 if((LocationName ==
"") && (
MidElement > -1))
9150 if((LocationName ==
"") && (
LagElement > -1))
9154 if(LocationName ==
"")
9156 throw Exception(
"Error - Location name not set in TrainAtLocation");
9167 for(
int x = 0; x < 4; x++)
9179 for(
int x = 0; x < 4; x++)
9196 AnsiString(LinkNumber) +
"," +
HeadCode);
9248 int DistanceToRedSignal = 0, DistanceToExit = -1;
9249 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9253 float MinsEarly = 0;
9254 TDateTime DepartureTime;
9255 TDateTime ArrivalTime;
9283 if(TempTTE < LastTimeToExit)
9318 if(TempTTE < LastTimeToExit)
9341 if(TempTTE < LastTimeToExit)
9371 if(TempTTE < LastTimeToExit)
9394 if(TempTTE < LastTimeToExit)
9437 float CurrentStopTime;
9438 float LaterStopTime;
9439 float RecoverableTime;
9447 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9454 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9455 bool DistanceToExitSet = (DistanceToExit > -1);
9456 int GenericDistance = DistanceToRedSignal;
9457 if(DistanceToExitSet)
9459 GenericDistance = DistanceToExit;
9475 float TimeToSubtract, TotalStopTime;
9478 TimeToSubtract = RecoverableTime;
9521 if(CurrentStopTime > 0)
9523 TotalStopTime = CurrentStopTime + LaterStopTime;
9532 else if((MinsEarly > 0) && !
Stopped())
9534 TotalStopTime = LaterStopTime + MinsEarly;
9538 if(LaterStopTime == 0)
9540 TotalStopTime = CurrentStopTime;
9546 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9549 if(AvTrackSpeed < 30)
9553 int Speed = AvTrackSpeed;
9563 if(DistanceToRedSignalSet)
9565 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9575 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9604 if((NextEntryPos == 0) || (NextEntryPos == 2))
9731 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9773 int IncrementalMinutes = 0;
9774 int IncrementalDigits = 0;
9782 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9818 if(AVEntry0.
Command ==
"Snt-sh")
9823 int IncrementalMinutes = 0;
9824 int IncrementalDigits = 0;
9832 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9876 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9956 AnsiString Loc =
"";
9957 bool ElementFound =
false;
9962 ElementFound =
true;
9967 ElementFound =
true;
9972 ElementFound =
true;
10001 else if(AVEntryPtr->
Command ==
"Fer")
10003 bool CorrectExit =
false;
10010 CorrectExit =
true;
10115 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10133 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10148 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10159 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10160 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10161 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10163 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10164 "," + AnsiString(Mass) +
"," + ModeStr);
10166 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10168 int RearExitPos = -1;
10170 for(
int x = 0; x < 4; x++)
10177 if(RearExitPos == -1)
10179 throw Exception(
"Error, RearExit == -1 in AddTrain");
10181 bool ReportFlag =
true;
10186 ReportFlag =
false;
10198 if(ModeStr ==
"Timetable")
10204 if(MaxRunningSpeed < 10)
10206 MaxRunningSpeed = 10;
10208 if(SignallerSpeed < 10)
10210 SignallerSpeed = 10;
10212 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10213 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10220 if(SignallerControl)
10250 if(!SignallerControl)
10265 if(!SignallerControl)
10276 AnsiString Loc =
"";
10293 if(!SignallerControl)
10312 int RouteNumber = -1;
10313 bool SignalsSet =
false;
10320 int RouteStartPosition;
10324 if(FirstPair.first == RouteNumber)
10326 RouteStartPosition = FirstPair.second;
10328 else if(SecondPair.first == RouteNumber)
10330 RouteStartPosition = SecondPair.second;
10334 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10340 else if(RouteNumber > -1)
10360 int LinkedRouteNumber = -1;
10381 int RouteStartPosition;
10385 if(FirstPair.first == RouteNumber)
10387 RouteStartPosition = FirstPair.second;
10389 else if(SecondPair.first == RouteNumber)
10391 RouteStartPosition = SecondPair.second;
10395 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10401 else if(RouteNumber > -1)
10421 int LinkedRouteNumber = -1;
10442 AnsiString(TrackVectorNumber));
10445 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10454 throw Exception(
"Error, VecPos not set in EntryPos");
10456 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10461 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10466 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10480 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10488 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10498 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10519 return(RepeatTime);
10528 AnsiString RetStr =
"", PartStr =
"";
10536 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10544 if(Ptr->SignallerControl)
10546 RetStr =
"Train under signaller control";
10551 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10562 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10566 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10570 else if(Ptr->FormatType ==
PassTime)
10574 else if(Ptr->Command ==
"Fns")
10580 else if(Ptr->Command ==
"F-nshs")
10583 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10590 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10597 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10600 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10603 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10610 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10612 PartStr =
"Terminate at " + Ptr->LocationName;
10614 else if(Ptr->Command ==
"Frh")
10616 PartStr =
"Terminate at " + Ptr->LocationName;
10618 else if(Ptr->Command ==
"Fer")
10620 AnsiString AllowedExits;
10624 else if(Ptr->Command ==
"Fjo")
10627 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10629 else if(Ptr->Command ==
"jbo")
10632 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10634 else if(Ptr->Command ==
"fsp")
10639 else if(Ptr->Command ==
"rsp")
10644 else if(Ptr->Command ==
"cdt")
10648 else if(Ptr->Command ==
"dsc")
10654 RetStr = RetStr +
'\n' + PartStr;
10662 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10673 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
10676 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10677 AnsiString DepTime =
"", EventTime =
"";
10678 bool CDTFlag =
false;
10680 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10681 AnsiString TowardsLocation =
"";
10684 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10686 TowardsLocation = AVI->LocationName;
10688 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10697 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10703 if(AVI->Command ==
"cdt")
10705 CDTFlag = !CDTFlag;
10708 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10711 RetStr +=
"\nNew service splits at " + EventTime;
10715 if(AVI->Command ==
"jbo")
10718 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10722 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10725 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10729 if(AVI->Command ==
"Fjo")
10732 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10736 if(AVI->Command ==
"Frh")
10738 RetStr +=
"\nNew service finishes and remains at location.";
10742 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10747 if(TowardsLocation !=
"")
10749 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10753 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10758 if(TowardsLocation !=
"")
10760 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10764 RetStr +=
"\nNew service departs at " + DepTime;
10929 ActiveTrackElementNameMapEntry.second = 0;
10935 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10938 if(TTBLFile.is_open())
10940 char *TrainTimetableString =
new char[10000];
10942 bool EndOfFile =
false;
10945 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10947 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10954 delete[] TrainTimetableString;
10958 AnsiString OneLine(TrainTimetableString);
10959 bool FinalCallFalse =
false;
10960 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10964 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10965 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10970 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10972 delete[] TrainTimetableString;
10976 OneLine = AnsiString(TrainTimetableString);
10982 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10984 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10994 OneLine = AnsiString(TrainTimetableString);
10996 if(OneLine.Length() > 9999)
10998 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11000 delete[] TrainTimetableString;
11004 bool FinalCallFalse =
false;
11005 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11009 delete[] TrainTimetableString;
11013 if(EndOfFile && (Count < 2))
11016 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11018 delete[] TrainTimetableString;
11024 delete[] TrainTimetableString;
11029 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11040 bool CheckLocationsExistInRailway)
11168 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11178 if(OneLine[1] !=
'*')
11180 int SCPos = OneLine.Pos(
';');
11191 bool AllCommas =
true;
11193 for(
int x = 1; x < OneLine.Length() + 1; x++)
11195 if(OneLine[x] !=
',')
11200 if(AllCommas || (OneLine ==
""))
11215 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11216 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11217 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11218 TDateTime StartTime(0);
11220 bool Warning =
false;
11247 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11248 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11249 double MaxBrakeRate = 0;
11250 double PowerAtRail = 0;
11251 int SignallerSpeed = 0;
11252 if(OneLine[1] ==
'*')
11258 int Pos = OneLine.Pos(
',');
11261 int SubStringLength = 20;
11262 if(OneLine.Length() < 20)
11264 SubStringLength = OneLine.Length();
11266 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11270 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11271 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11282 TempTrainDataEntry.
HeadCode = HeadCode;
11286 if(Description !=
"")
11291 TempTrainDataEntry.
Mass = Mass;
11299 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11302 while(NewRemainder[NewRemainder.Length()] ==
',')
11304 if(NewRemainder.Length() > 1)
11306 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11315 if(NewRemainder ==
"")
11317 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11322 int CommaCount = 0;
11323 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11325 if(NewRemainder[x] ==
',')
11330 if(CommaCount == 0)
11332 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11334 int SubStringLength = 20;
11335 if(OneLine.Length() < 20)
11337 SubStringLength = OneLine.Length();
11340 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11341 OneLine.SubString(1, SubStringLength) +
"'....");
11346 AnsiString OneEntry =
"";
11351 bool FinishFlag =
false;
11353 for(
int x = 0; x < CommaCount + 1; x++)
11355 if((CommaCount == 0) || (x < CommaCount))
11360 if(CommaCount == 0)
11362 OneEntry = NewRemainder;
11367 Pos = NewRemainder.Pos(
',');
11368 OneEntry = NewRemainder.SubString(1, Pos - 1);
11369 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11375 RearStartOrRepeatMins = 0;
11376 FrontStartOrRepeatDigits = 0;
11377 NumberOfRepeats = 0;
11378 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11379 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11381 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11392 if(Warning && (Second ==
"Frh"))
11394 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11398 if(Warning && (Second ==
"Fjo"))
11401 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11438 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11442 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11444 if(NewRemainder[1] !=
'R')
11447 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11453 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11457 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11460 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11466 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11471 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11476 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11479 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11495 TDateTime TempTime;
11501 ActionVectorEntry.
Warning = Warning;
11517 ActionVectorEntry.
Command = Second;
11532 else if(FormatType ==
TimeCmd)
11538 ActionVectorEntry.
Command = Second;
11546 ActionVectorEntry.
Command = Second;
11547 ActionVectorEntry.
ExitList = ExitList;
11555 ActionVectorEntry.
Command = Second;
11569 ActionVectorEntry.
Command = Second;
11580 ActionVectorEntry.
Command = Second;
11590 ActionVectorEntry.
Command = Second;
11592 if((Second ==
"fsp") || (Second ==
"rsp"))
11607 ActionVectorEntry.
Command = Second;
11616 ActionVectorEntry.
Command = Second;
11622 ActionVectorEntry.
Command = Second;
11630 ActionVectorEntry.
Command = Second;
11633 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11638 OneEntry = NewRemainder;
11643 RearStartOrRepeatMins = 0;
11644 FrontStartOrRepeatDigits = 0;
11645 NumberOfRepeats = 0;
11646 if((FinishFlag) && (OneEntry[1] !=
'R'))
11649 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11653 if(OneEntry[1] !=
'R')
11655 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11656 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11658 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'.\nIf the program version is not the latest the "
11659 "timetable may have features that aren't compatible with the version in use.");
11676 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11683 TDateTime TempTime;
11689 ActionVectorEntry.
Warning = Warning;
11696 ActionVectorEntry.
Command = Second;
11704 ActionVectorEntry.
Command = Second;
11713 ActionVectorEntry.
Command = Second;
11722 ActionVectorEntry.
Command = Second;
11732 ActionVectorEntry.
Command = Second;
11733 ActionVectorEntry.
ExitList = ExitList;
11737 ActionVectorEntry.
Command = Second;
11739 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11744 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11760 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11779 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11784 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11799 if(TimeStr.Length() < 5)
11804 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11809 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11814 if(TimeStr[3] !=
':')
11819 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11824 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11829 while(TimeStr.Length() > 5)
11831 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11833 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11834 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11836 if((WholeHours + FracHour) >= 95.98334)
11841 Time = TDateTime((WholeHours + FracHour) / 24);
11848 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11849 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11858 TDateTime TempTime;
11860 if(OneEntry.Length() > 0)
11862 if(OneEntry[1] ==
'W')
11865 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11869 if(OneEntry ==
"Frh")
11879 if(OneEntry.Length() < 7)
11884 int Pos = OneEntry.Pos(
';');
11892 First = OneEntry.SubString(1, 5);
11898 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11901 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
11904 if(Remainder.Length() < 7)
11909 Pos = Remainder.Pos(
';');
11916 Second = Remainder.SubString(1, 5);
11922 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11935 Pos = Remainder.Pos(
';');
11938 Second = Remainder;
11939 if(Second ==
"cdt")
11964 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11970 Second = Remainder.SubString(1, Pos - 1);
11972 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11974 Pos = Remainder.Pos(
';');
11981 Third = Remainder.SubString(1, Pos - 1);
11982 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11985 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11988 int SpacePos = Third.Pos(
' ');
11994 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11995 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11997 if(CheckLocationsExistInRailway)
12007 if(Second ==
"Snt")
12030 if(Second ==
"Sns-sh")
12049 if(Second ==
"F-nshs")
12063 if(Second ==
"Sns-fsh")
12077 if(Second ==
"Fns-sh")
12097 if(Second ==
"pas")
12112 if(Second ==
"Fer")
12119 if(CheckLocationsExistInRailway)
12130 if(Second ==
"dsc")
12132 if(Third.Length() > 60)
12134 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12138 for(
int x = 1; x < Third.Length() + 1; x++)
12141 if((Third[x] <
' ') && (Third[x] >= 0))
12143 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12159 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12160 (Second !=
"Frh-sh"))
12172 if(Second ==
"Frh-sh")
12180 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12184 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12188 if((Second ==
"Sfs") || (Second ==
"Sns"))
12193 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12210 bool ErrorFlag =
false;
12212 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12216 int pos = SplitDistributionString.Pos(
'-');
12223 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12224 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12227 int x = MassStr.ToInt();
12228 int y = PowerStr.ToInt();
12229 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12234 catch(
const Exception &e)
12241 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12242 "power for the new split-off train");
12263 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12268 for(
int x = 1; x < LocStr.Length() + 1; x++)
12270 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12284 if(CheckLocationsExistInRailway)
12289 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12290 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12291 "that includes a continuation will not be valid.");
12309 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12312 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12317 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12319 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12321 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12327 for(
int x = 3; x >= 0; x--)
12329 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12330 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12332 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12348 AnsiString CurrentID =
"";
12350 if(IDSet.Length() == 0)
12352 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12356 for(
int x = 1; x <= IDSet.Length(); x++)
12359 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12361 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12383 int Pos = IDSet.Pos(
' ');
12394 CurrentID = IDSet.SubString(1, Pos - 1);
12395 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12407 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12414 if(!ExitList.empty())
12416 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12418 if(*ELIT == VecPos)
12420 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12427 ExitList.push_back(VecPos);
12437 Pos = IDSet.Pos(
' ');
12444 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12451 AnsiString Remainder =
"";
12452 int SemiColonCount = 0;
12454 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12456 if(TrainInfoStr[x] ==
';')
12461 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12463 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12464 "'. Should be headcode + optional description for a continuing service;" +
12465 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12469 if(SemiColonCount == 0)
12471 HeadCode = TrainInfoStr;
12480 if(SemiColonCount == 1)
12482 Pos = TrainInfoStr.Pos(
';');
12483 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12484 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12490 if(Description ==
"")
12492 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12496 if(Description.Length() > 60)
12498 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12502 for(
int x = 1; x < Description.Length() + 1; x++)
12505 if((Description[x] <
' ') && (Description[x] >= 0))
12507 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12516 Pos = TrainInfoStr.Pos(
';');
12517 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12518 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12524 Pos = Remainder.Pos(
';');
12525 Description = Remainder.SubString(1, Pos - 1);
12526 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12527 if(Description ==
"")
12529 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12533 if(Description.Length() > 60)
12535 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12539 for(
int x = 1; x < Description.Length() + 1; x++)
12542 if((Description[x] <
' ') && (Description[x] >= 0))
12544 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12549 Pos = Remainder.Pos(
';');
12550 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12552 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12553 if(StartSpeedStr ==
"")
12555 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12559 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12561 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12563 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12568 StartSpeed = StartSpeedStr.ToInt();
12574 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12578 Pos = Remainder.Pos(
';');
12579 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12581 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12582 if(MaxRunningSpeedStr ==
"")
12584 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12588 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12590 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12592 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12597 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12603 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12607 if(MaxRunningSpeed < 10)
12610 MaxRunningSpeed = 10;
12613 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12617 Pos = Remainder.Pos(
';');
12618 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12620 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12623 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12627 for(
int x = 1; x < MassStr.Length() + 1; x++)
12629 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12631 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12636 Mass = MassStr.ToInt() * 1000;
12642 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12648 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12652 Pos = Remainder.Pos(
';');
12653 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12655 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12656 if(MaxBrakeForceStr ==
"")
12658 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12662 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12664 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12666 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12671 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12674 if((MaxBrakeForce / Mass) > 1)
12676 MaxBrakeForce = Mass;
12679 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12683 if((MaxBrakeForce / Mass) < 0.01)
12685 MaxBrakeForce = Mass * 0.01;
12688 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12693 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12695 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12697 if(SemiColonCount == 6)
12699 GrossPowerStr = Remainder;
12700 SignallerSpeedStr =
"30";
12704 Pos = Remainder.Pos(
';');
12705 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12706 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12709 if(GrossPowerStr ==
"")
12711 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12715 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12717 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12719 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12725 double GrossPower = GrossPowerStr.ToInt() * 1000;
12732 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12736 else if(GrossPower == 0)
12741 else if((GrossPower > 0) && (GrossPower < 10000))
12744 GrossPower = 10000;
12746 PowerAtRail = GrossPower * 0.8;
12750 if(SignallerSpeedStr ==
"")
12752 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12756 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12758 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12760 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12765 SignallerSpeed = SignallerSpeedStr.ToInt();
12771 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12775 if(SignallerSpeed < 10)
12778 SignallerSpeed = 10;
12781 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12799 if(OneEntry.Length() < 7)
12801 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12805 int SemiColonCount = 0;
12807 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12809 if(OneEntry[x] ==
';')
12814 if(SemiColonCount != 3)
12816 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12820 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12822 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12826 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12831 Pos = Remainder.Pos(
';');
12832 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12834 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12835 if(MinutesStr ==
"")
12837 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12841 if(MinutesStr.Length() > 3)
12844 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12848 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12850 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12852 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12857 RearStartOrRepeatMins = MinutesStr.ToInt();
12858 if(RearStartOrRepeatMins == 0)
12860 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12864 Pos = Remainder.Pos(
';');
12865 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12867 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12868 if(DigitsStr ==
"")
12870 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12874 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12876 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12878 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12883 if(DigitsStr.Length() > 2)
12885 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12889 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12903 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12907 AnsiString NumberStr = Remainder;
12909 if(NumberStr ==
"")
12911 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12915 if(NumberStr.Length() > 4)
12918 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12922 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12924 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12927 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12932 NumberOfRepeats = NumberStr.ToInt();
12933 if(NumberOfRepeats == 0)
12935 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13209 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13230 TwoLocationFlag =
false;
13236 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13250 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13266 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13278 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13304 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13317 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
13318 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
13319 "location of any other type of finish.");
13325 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13331 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
13332 "event for: " + TDEntry.
HeadCode);
13342 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13347 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13357 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13362 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13372 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13383 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13393 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13405 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13412 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13421 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13440 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13442 AnsiString LocationName =
"";
13456 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13457 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13466 if(AVEntry0.
Command ==
"Snt-sh")
13480 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13496 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13497 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13509 bool FoundFlag =
false;
13513 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13515 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13527 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13540 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13565 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13587 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13609 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13634 bool LocFoundFlag, FnsFoundFlag;
13638 LocFoundFlag =
false;
13639 FnsFoundFlag =
false;
13640 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13645 FnsFoundFlag =
true;
13654 LocFoundFlag =
true;
13665 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13666 "by an event at the same location that has an identified location name, normally an arrival, see "
13673 if(FnsFoundFlag && !LocFoundFlag)
13675 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13676 "by an event at the same location that has an identified location name, normally an arrival, see "
13690 if(AVEntry0.
Command ==
"Sns")
13702 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13710 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13711 ". The event isn't valid for a stationary train.");
13719 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13726 TDateTime SnsEventTime = AVEntry0.
EventTime;
13729 bool BreakFlag =
false;
13732 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13737 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13759 if(AVEntry0.
Command ==
"Sfs")
13761 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13769 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13781 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13786 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13806 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13813 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13828 if(AVEntry0.
Command ==
"Sfs")
13840 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13848 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13849 ". The event isn't valid for a stationary train.");
13857 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13864 TDateTime SfsEventTime = AVEntry0.
EventTime;
13866 bool BreakFlag =
false;
13869 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13874 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13894 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13899 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13920 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13927 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13932 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
13935 "Please make sure that the finish event of the service that links to this event is preceded by an "
13936 "event at the same location that has an identified location name, normally an arrival.");
13941 else if(AVEntry.
Command ==
"Snt-sh")
13944 "Please make sure that the service starts with zero speed and is at a named location.");
13949 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
13952 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
13959 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13972 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13982 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
13989 if(AVEntry.
Command ==
"F-nshs")
13994 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14022 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14023 ". The event isn't valid for a stationary train.");
14033 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14041 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14042 ". The event isn't valid for a stationary train.");
14060 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14061 ". The event isn't valid for a stationary train.");
14079 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14080 ". The event isn't valid for a stationary train.");
14090 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14098 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14099 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14117 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14118 ". The event isn't valid for a moving train.");
14140 bool LastEntryIsAnArrival =
false;
14147 LastEntryIsAnArrival =
false;
14148 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14155 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14157 if(LastEntryIsAnArrival)
14161 LastEntryIsAnArrival =
false;
14167 LastEntryIsAnArrival =
true;
14174 LastEntryIsAnArrival =
true;
14175 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14182 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14184 if(LastEntryIsAnArrival)
14188 LastEntryIsAnArrival =
false;
14194 LastEntryIsAnArrival =
true;
14204 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14212 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14220 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14221 ". The event isn't valid for a stationary train.");
14232 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14240 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14241 ". The event isn't valid for a moving train.");
14255 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14262 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14266 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14273 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14277 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14286 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14290 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14297 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14308 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14323 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14331 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14346 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14358 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14370 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14371 ", may be before timetable start time");
14382 AnsiString LastLocationName =
"";
14386 bool LastEntryIsAnArrival =
false;
14391 LastEntryIsAnArrival =
false;
14392 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14393 if(LastLocationName !=
"")
14395 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14397 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14410 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14422 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14435 TwoLocationFlag =
true;
14440 LastEntryIsAnArrival =
false;
14444 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14447 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14452 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14455 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14461 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14467 LastEntryIsAnArrival =
true;
14468 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14469 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14481 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14493 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14506 TwoLocationFlag =
true;
14511 LastEntryIsAnArrival =
false;
14515 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14518 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14526 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14533 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14541 AnsiString LocationNameToBeChecked =
"";
14546 unsigned int y = 0;
14560 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14561 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14579 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14588 TwoLocationFlag =
true;
14599 if(TwoLocationFlag)
14609 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14614 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14616 AnsiString LocName =
"";
14622 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14629 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14652 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14677 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14699 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14721 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14740 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14743 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14758 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14763 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14767 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14771 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14775 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14814 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14816 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14822 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14835 int IncMinutes = 0;
14845 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14851 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14857 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14862 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14868 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14873 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14886 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14912 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14920 if(HeadCode.Length() > 4)
14922 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
14933 int ForwardCount = 0;
14934 int ReverseCount = 0;
14936 if(MainHeadCode == SecondHeadCode)
14938 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14947 if(TDEntry.
HeadCode == MainHeadCode)
14949 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14964 if(ForwardCount == 0)
14967 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14969 if(ForwardCount > 2)
14972 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14973 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14982 if(TDEntry.
HeadCode == SecondHeadCode)
14984 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14999 if(ReverseCount == 0)
15001 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15006 if(ReverseCount > 2)
15009 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15010 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15015 if(ForwardCount != ReverseCount)
15017 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15018 " than the other way round");
15049 int ForwardCount = 0;
15050 int ReverseCount = 0;
15051 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15060 if(TDEntry.
HeadCode == MainHeadCode)
15062 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15065 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15070 ForwardEntryPtr = &AVEntry;
15072 ForwardTDVectorNumber = x;
15075 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15076 (AVEntry.
Command ==
"Frh-sh")))
15081 ForwardEntryPtr = &AVEntry;
15083 ForwardTDVectorNumber = x;
15089 if(ForwardCount == 0)
15092 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15094 if(ForwardCount > 1)
15096 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15106 if(TDEntry.
HeadCode == OtherHeadCode)
15108 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15111 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15117 ReverseEntryPtr = &AVEntry;
15118 ReverseTDVectorNumber = x;
15121 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15127 ReverseEntryPtr = &AVEntry;
15128 ReverseTDVectorNumber = x;
15135 if(ReverseCount == 0)
15137 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15142 if(ReverseCount > 1)
15144 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15151 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15152 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15153 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15154 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15158 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15165 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15170 if(SetDataAndCheckLocations)
15172 if(ForwardEntryPtr->LocationName ==
"")
15174 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15175 ". One or other service does not have a location set");
15182 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15183 ". One or other service does not have a location set");
15188 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15190 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15191 " is at a different location to the referencing train " + MainHeadCode);
15200 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15202 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15203 " has a different event time to the referencing train " + MainHeadCode);
15211 if(ForwardShuttleStart && ReverseShuttleFinish)
15216 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15217 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15223 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15226 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15228 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15229 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15235 if(ReverseEntryPtr->
Command ==
"Fjo")
15238 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15240 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15241 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15247 if(ReverseEntryPtr->
Command ==
"Fns")
15250 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15252 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15253 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15259 if(ForwardEntryPtr->Command ==
"Sfs")
15261 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15264 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15271 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15273 if(ReverseEntryPtr->
Command !=
"Sfs")
15275 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15283 if(SetDataAndCheckLocations)
15287 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15294 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15300 bool StationLocation =
false;
15303 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
15307 StationLocation =
true;
15311 if(StationLocation)
15315 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15325 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15331 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15343 if(ForwardEntryPtr->Command ==
"Sns")
15345 if(ReverseEntryPtr->
Command !=
"Fns")
15347 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15348 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15354 if(ForwardEntryPtr->Command ==
"Fns")
15356 if(ReverseEntryPtr->
Command !=
"Sns")
15358 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15359 " and forms a new service with headcode " + OtherHeadCode);
15366 if(SetDataAndCheckLocations)
15368 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15380 if(ForwardEntryPtr->Command ==
"jbo")
15382 if(ReverseEntryPtr->
Command !=
"Fjo")
15384 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15385 " and is joined by a train with headcode " + OtherHeadCode);
15391 if(ForwardEntryPtr->Command ==
"Fjo")
15393 if(ReverseEntryPtr->
Command !=
"jbo")
15395 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15396 " and joins a train with headcode " + OtherHeadCode);
15403 if(SetDataAndCheckLocations)
15405 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15421 if(ForwardShuttleStart)
15424 if(!ReverseShuttleFinish)
15427 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15428 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15434 if(ReverseShuttleStart)
15437 if(!ForwardShuttleFinish)
15440 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15441 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15448 if(SetDataAndCheckLocations)
15450 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15463 bool MainRepeat =
false, OtherRepeat =
false;
15473 OtherRepeat =
true;
15476 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15478 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15479 " and the associated train with headcode " + OtherHeadCode);
15484 if(MainRepeat && OtherRepeat)
15490 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15491 " and the associated train with headcode " + OtherHeadCode);
15513 while(Input[1] ==
' ')
15515 if(Input.Length() > 1)
15517 Input = Input.SubString(2, Input.Length() - 1);
15531 while(Input[Input.Length()] ==
' ')
15533 if(Input.Length() > 1)
15535 Input = Input.SubString(1, Input.Length() - 1);
15545 AnsiString Output =
"";
15546 bool DelimiterFound =
false;
15548 for(
int x = 1; x < Input.Length() + 1; x++)
15552 if(Input[x] ==
' ')
15557 if((Input[x] !=
',') && (Input[x] !=
';'))
15559 DelimiterFound =
false;
15560 Output = Output + Input[x];
15564 DelimiterFound =
true;
15565 Output = Output + Input[x];
15577 DelimiterFound =
false;
15578 for(
int x = Input.Length(); x > 0; x--)
15582 if(Input[x] ==
' ')
15587 if((Input[x] !=
',') && (Input[x] !=
';'))
15589 DelimiterFound =
false;
15590 Output = AnsiString(Input[x]) + Output;
15594 DelimiterFound =
true;
15595 Output = AnsiString(Input[x]) + Output;
15620 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15622 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15634 LocationName = LocRear;
15638 LocationName = LocFront;
15640 if(LocationName ==
"")
15661 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15702 int RearPosition = 0, FrontPosition = 0;
15705 if(RearPosition < 0)
15712 if(FrontPosition < 0)
15724 for(
int x = 0; x < 4; x++)
15726 if(RearTrackElement.
Conn[x] == FrontPosition)
15741 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15748 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15754 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15785 AnsiString(RearExitPos));
15796 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15798 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15801 AnsiString RearName, FrontName;
15817 FrontName = FrontTrackElement.
ElementID;
15820 int LockedVectorNumber;
15940 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
15945 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
15953 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
15958 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
15992 "," + AnsiString(IncDigits));
15995 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16000 return(BaseHeadCode);
16002 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16003 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16005 while(NextRepeatDigits >= 100)
16007 NextRepeatDigits -= 100;
16009 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16011 if(NextRepeatDigitsStr.Length() < 2)
16013 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16015 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16018 return(NextRepeatHeadCode);
16026 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16027 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16029 return(NextRepeatTime);
16038 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16039 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16040 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16041 int RepeatSecs = RepeatMinutes * 60;
16043 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16077 NonRepeatingHeadCode);
16078 int ForwardCount = 0;
16079 int ReverseCount = 0;
16080 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16090 if(TDEntry.
HeadCode == MainHeadCode)
16092 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16098 ForwardEntryPtr = &AVEntry;
16100 ForwardTDVectorNumber = x;
16105 if(ForwardCount == 0)
16108 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16110 if(ForwardCount > 1)
16112 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16122 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16124 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16131 ReverseEntryPtr = &AVEntry;
16132 ReverseTDVectorNumber = x;
16138 if(ReverseCount == 0)
16140 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16145 if(ReverseCount > 1)
16147 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16148 NonRepeatingHeadCode);
16153 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16155 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16160 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16162 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16167 if(SetDataAndCheckLocations)
16169 if(ForwardEntryPtr->LocationName ==
"")
16171 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16172 ". One or other service does not have a location set");
16179 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16180 ". One or other service does not have a location set");
16185 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16187 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16188 " is at a different location to the referencing train " + MainHeadCode);
16194 if(ForwardEntryPtr->Command ==
"F-nshs")
16197 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16199 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16200 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16206 if(ForwardEntryPtr->Command ==
"Fns-sh")
16210 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16212 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16213 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16219 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16222 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16224 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16225 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16243 if(ForwardEntryPtr->Command ==
"Sns-sh")
16245 if(ReverseEntryPtr->
Command !=
"F-nshs")
16247 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16248 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16254 if(ForwardEntryPtr->Command ==
"F-nshs")
16256 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16258 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16259 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16266 if(SetDataAndCheckLocations)
16268 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16280 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16282 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16285 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16286 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16292 if(ForwardEntryPtr->Command ==
"Fns-sh")
16294 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16297 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16298 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16305 if(SetDataAndCheckLocations)
16307 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16331 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16332 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16333 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16334 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16336 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16360 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16363 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16364 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16366 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16368 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16373 while(LastActionCommand ==
"Fns")
16375 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16376 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16377 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16380 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16381 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16388 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16391 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16392 ". The linking of two or more shuttles is not permitted.");
16412 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
16430 ShowMessage(Message);
16439 int Mins = Input, Hrs = 0;
16445 AnsiString AnsiMins = AnsiString(Mins);
16446 if(AnsiMins.Length() == 1)
16448 AnsiMins =
"0" + AnsiMins;
16450 AnsiString AnsiHrs = AnsiString(Hrs);
16451 if(AnsiHrs.Length() == 1)
16453 AnsiHrs =
"0" + AnsiHrs;
16456 return(AnsiHrs +
':' + AnsiMins);
16499 AnsiString(ActionEventType) +
"," + LocationID);
16500 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16505 Prefix =
" ERROR: ";
16508 Prefix =
" HELD: ";
16509 ErrorLog =
" can't enter railway, train obstructing entry position ";
16510 WarningStr =
" can't enter railway, train obstructing entry position ";
16515 Prefix =
" HELD: ";
16516 ErrorLog =
" can't enter railway, route set against it at entry position ";
16517 WarningStr =
" can't enter railway, route set against it at entry position ";
16522 Prefix =
" HELD: ";
16523 ErrorLog =
" can't be created, train obstructing ";
16524 WarningStr =
" can't be created, train obstructing ";
16529 Prefix =
" HELD: ";
16530 ErrorLog =
" can't be created on a locked route at ";
16531 WarningStr =
" can't be created on a locked route at ";
16536 Prefix =
" HELD: ";
16537 ErrorLog =
" can't enter on a locked route at ";
16538 WarningStr =
" can't enter on a locked route at ";
16543 Prefix =
" HELD: ";
16544 ErrorLog =
" can't be created, points set wrongly at ";
16545 WarningStr =
" can't be created, points set wrongly at ";
16550 ErrorLog =
" left railway unexpectedly at ";
16555 ErrorLog =
" left railway at an incorrect exit at ";
16560 ErrorLog =
" failed to split - location too short at ";
16561 WarningStr =
" failed to split, location too short at ";
16566 Prefix =
" HELD: ";
16567 ErrorLog =
" unable to split - other train obstructing at ";
16568 WarningStr =
" unable to split - other train obstructing at ";
16573 ErrorLog =
" stopped at buffers unexpectedly at position ";
16577 ErrorLog =
" failed to stop at ";
16582 ErrorLog =
" failed to split at ";
16587 ErrorLog =
" failed to be joined by other train at ";
16592 ErrorLog =
" failed to change its description at ";
16597 ErrorLog =
" failed to join other train at ";
16602 ErrorLog =
" failed to terminate at ";
16607 ErrorLog =
" failed to form new service at ";
16612 ErrorLog =
" failed to exit railway ";
16617 ErrorLog =
" failed to change direction at ";
16622 ErrorLog =
" failed to pass ";
16627 ErrorLog =
" facing buffers and unable to start at ";
16631 ErrorLog =
" DERAILED at position ";
16632 Prefix =
" DERAILMENT: ";
16637 ErrorLog =
" CRASHED INTO BUFFERS at ";
16638 Prefix =
" CRASH: ";
16643 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16644 Prefix =
" CRASH: ";
16649 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16650 Prefix =
" CRASH: ";
16654 else if(ActionEventType ==
FailSPAD)
16656 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16657 Prefix =
" SPAD: ";
16662 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16663 Prefix =
" SPAD RISK: ";
16668 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16672 Prefix =
" WARNING: ";
16673 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16674 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16679 Prefix =
" WARNING: ";
16680 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16681 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16686 Prefix =
" WARNING: ";
16687 ErrorLog =
" is without power so it can't depart from ";
16688 WarningStr =
" is without power so it can't depart from ";
16693 Prefix =
" WARNING: ";
16694 ErrorLog =
" can't depart because there is a train in front at ";
16695 WarningStr =
" can't depart because there is a train in front at ";
16733 std::ofstream OutFile(
"TrainData.csv");
16737 ShowMessage(
"Output file TrainData.csv failed to open");
16744 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16749 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16750 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16751 "RepeatNumber" <<
'\n' <<
'\n';
16752 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16755 AnsiString TimetableEntryTypeStr;
16761 TimetableEntryTypeStr =
"NoFormat";
16767 TimetableEntryTypeStr =
"TimeLoc";
16773 TimetableEntryTypeStr =
"TimeTimeLoc";
16779 TimetableEntryTypeStr =
"TimeCmd";
16785 TimetableEntryTypeStr =
"StartNew";
16791 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16797 TimetableEntryTypeStr =
"FinRemHere";
16803 TimetableEntryTypeStr =
"FNSShuttle";
16809 TimetableEntryTypeStr =
"SNTShuttle";
16815 TimetableEntryTypeStr =
"SNSShuttle";
16821 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16827 TimetableEntryTypeStr =
"FSHNewService";
16833 TimetableEntryTypeStr =
"Repeat";
16839 TimetableEntryTypeStr =
"Default";
16850 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16851 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16854 AnsiString RunningEntryStr;
16860 RunningEntryStr =
"NotStarted";
16866 RunningEntryStr =
"Running";
16872 RunningEntryStr =
"Exited";
16876 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16893 ShowMessage(Message);
16894 BaseTime = TDateTime::CurrentDateTime();
16908 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16921 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16923 for(
int x = 0; x < NumberOfTrains; x++)
16925 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16945 int NumberOfTrains;
16952 for(
int x = 0; x < NumberOfTrains; x++)
16989 for(
int x = 0; x < LockedRouteVectorSize; x++)
16996 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17007 int LockedRouteVectorSize;
17014 for(
int x = 0; x < LockedRouteVectorSize; x++)
17072 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17080 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17091 int ContinuationAutoSigVectorSize;
17098 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17168 if(AVFirstEntry.
Command ==
"Snt")
17192 CTEMMP.second = CTEEntry;
17199 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17207 CTEMMP.second = CTEEntry;
17228 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17245 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17247 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17258 AnsiString RetStr =
"", PartStr =
"";
17373 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17377 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17379 AnsiString ShortTTName =
"";
17381 for(
int x = TTFileName.Length(); x > 0; x--)
17383 if(TTFileName[x] ==
'\\')
17385 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17390 ShowMessage(
"Creates two timetables named " + ShortTTName +
17391 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17393 Screen->Cursor = TCursor(-11);
17395 AnsiString FormatNoDPStr =
"#######0";
17396 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17399 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17406 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17408 if(TrainDataEntry.
Mass > 0)
17410 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17414 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17418 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17422 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17424 FirstHeadCode = TrainDataEntry.
HeadCode;
17425 int IncDigits = 0, IncMinutes = 0;
17427 if(!ActionVector.empty())
17429 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17431 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17432 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17450 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17455 AnsiString PartStr =
"", TimeStr =
"";
17472 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17476 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17486 PartStr =
"Enters at " + LocName;
17499 PartStr =
"Created at " + LocName;
17513 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17518 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17524 else if(ActionVectorEntry.
Command ==
"Sfs")
17526 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17530 else if(ActionVectorEntry.
Command ==
"Sns")
17532 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17540 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17546 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17554 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17557 AnsiString FirstHeadCode = TDE->
HeadCode;
17561 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17573 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17575 OneTTEntry.
Action = PartStr;
17576 OneTTEntry.
Time = TimeStr;
17578 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17583 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17589 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17594 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17602 else if(ActionVectorEntry.
Command ==
"jbo")
17604 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17608 else if(ActionVectorEntry.
Command ==
"fsp")
17612 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17616 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17621 else if(ActionVectorEntry.
Command ==
"rsp")
17625 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17629 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17634 else if(ActionVectorEntry.
Command ==
"cdt")
17636 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17639 else if(ActionVectorEntry.
Command ==
"dsc")
17641 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17647 if(ActionVectorEntry.
Command ==
"Fns")
17649 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17653 else if(ActionVectorEntry.
Command ==
"F-nshs")
17655 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17661 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17668 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17674 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17681 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17686 else if(ActionVectorEntry.
Command ==
"Frh")
17688 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17693 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17697 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17707 else if(ActionVectorEntry.
Command ==
"Fer")
17709 AnsiString AllowedExits;
17713 else if(ActionVectorEntry.
Command ==
"Fjo")
17715 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17724 OneTTEntry.
Action = PartStr;
17725 OneTTEntry.
Time = TimeStr;
17732 AllTTTrains->push_back(OneTTLine);
17736 std::ofstream TTFile(TTFileName.c_str());
17740 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17741 delete AllTTTrains;
17776 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17777 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17779 TTFile << AllTTTrains->at(x).Header.c_str();
17782 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17784 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17786 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17790 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17793 TTFile <<
'\n' <<
'\n';
17795 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17797 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17798 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17800 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17802 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17806 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17811 TTFile <<
'\n' <<
'\n';
17816 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17818 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17820 std::ofstream TTFile2(TTFileName2.c_str());
17824 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17825 delete AllTTTrains;
17829 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17830 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17831 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17833 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17838 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17839 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17841 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17843 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17845 bool GiveMessagesFalse =
false;
17846 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17847 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17848 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17853 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17854 TimeString = TimeString.SubString(9, 5);
17855 ActionString +=
" " + OtherHeadCode;
17857 if(TimeString.SubString(1, 7) ==
"End at ")
17860 TimeString = TimeString.SubString(8, 5);
17862 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17863 AnsiMultiMapEntry.first = TimeString;
17864 AnsiMultiMapEntry.second = OneLine;
17865 TAMM->insert(AnsiMultiMapEntry);
17870 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17872 TTFile2 << (AMMIT->second).c_str();
17874 delete AllTTTrains;
17883 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17887 bool AnalysisError =
false;
17888 AnsiString SequenceLog =
"SequenceLog\n";
17931 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17933 int IteratorNumber = 0;
17934 AnsiString AnsiSuffix =
"";
17941 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17944 AnsiSuffix = AnsiString(Suffix);
17945 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17946 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17952 int Increment = 0, SlashPos;
17954 AnsiString LinkedHeadCode;
17958 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
17960 if(AVEIt->LinkedTrainEntryPtr != NULL)
17969 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17971 if(LinkedHeadCode[x] ==
'/')
17973 SlashPos = LinkedHeadCode.Length() - x + 1;
17976 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17977 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17978 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17984 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17988 AVEIt->OtherHeadCode =
"";
17990 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
17992 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
17996 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
17999 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18001 if(LinkedHeadCode[x] ==
'/')
18003 SlashPos = LinkedHeadCode.Length() - x + 1;
18006 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18007 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18008 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18014 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18018 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18023 SequenceLog +=
"1\n";
18026 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18032 ServiceCallingLocsList.clear();
18033 if(ActionVector.empty())
18037 if(ActionVector.at(0).SignallerControl)
18041 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18059 int HLoc = TE.
HLoc;
18060 int VLoc = TE.
VLoc;
18061 AnsiString HString;
18062 AnsiString VString;
18065 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18069 HString = AnsiString(HLoc);
18073 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18077 VString = AnsiString(VLoc);
18079 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18102 else if(AVE.
Command ==
"cdt")
18115 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18124 ServiceCallingLocsList.push_back(LName);
18128 int HLoc = TE.
HLoc;
18129 int VLoc = TE.
VLoc;
18130 AnsiString HString;
18131 AnsiString VString;
18134 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18138 HString = AnsiString(HLoc);
18142 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18146 VString = AnsiString(VLoc);
18148 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18152 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18156 SequenceLog +=
"2\n";
18185 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18191 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18192 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18193 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18195 SequenceLog +=
"3\n";
18202 TDateTime LastTDTime;
18203 int IncMinutes = 0;
18205 if(ActionVector.empty())
18209 if(ActionVector.at(0).SignallerControl)
18213 if(AVLast->FormatType ==
Repeat)
18215 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18223 if(AVLast->ArrivalTime != TDateTime(-1))
18225 LastTDTime = AVLast->ArrivalTime;
18227 else if(AVLast->EventTime != TDateTime(-1))
18229 LastTDTime = AVLast->EventTime;
18248 SequenceLog +=
"4\n";
18285 int IncMinutes = 0;
18287 if(ActionVector.empty())
18291 if(ActionVector.at(0).SignallerControl)
18295 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18297 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18299 for(
int y = 0; y < NumTrains; y++)
18313 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18328 LocServiceTimesVector.push_back(TLSTEntry);
18331 AnsiString IncTime =
"", FoundStopTime =
"";
18332 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18334 if(ActionVector.at(a).FormatType ==
TimeLoc)
18345 if(FoundStopTime ==
"")
18347 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18349 int WhileCount = 0;
18358 if(IncTime >= FoundStopTime)
18362 LocServiceTimesVector.push_back(TLSTEntry);
18363 if(WhileCount > 2000)
18365 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18378 int HLoc = TE.
HLoc;
18379 int VLoc = TE.
VLoc;
18380 AnsiString HString;
18381 AnsiString VString;
18384 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18388 HString = AnsiString(HLoc);
18392 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18396 VString = AnsiString(VLoc);
18398 TLSTEntry.
Location = HString +
'-' + VString;
18402 LocServiceTimesVector.push_back(TLSTEntry);
18410 LocServiceTimesVector.push_back(TLSTEntry);
18412 AnsiString IncTime =
"", FoundStopTime =
"";
18413 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18415 if(ActionVector.at(a).FormatType ==
TimeLoc)
18426 if(FoundStopTime ==
"")
18428 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18430 int WhileCount = 0;
18439 if(IncTime >= FoundStopTime)
18443 LocServiceTimesVector.push_back(TLSTEntry);
18444 if(WhileCount > 2000)
18446 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18456 bool SkipAddingMinutes =
false;
18459 LocServiceTimesVector.push_back(TLSTEntry);
18461 AnsiString IncTime =
"", FoundStopTime =
"";
18462 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18464 if(ActionVector.at(a).FormatType ==
TimeLoc)
18472 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18476 LocServiceTimesVector.pop_back();
18477 SkipAddingMinutes =
true;
18482 if(FoundStopTime ==
"")
18484 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18486 if(!SkipAddingMinutes)
18488 int WhileCount = 0;
18497 if(IncTime >= FoundStopTime)
18501 LocServiceTimesVector.push_back(TLSTEntry);
18502 if(WhileCount > 2000)
18504 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18513 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18515 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18517 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18518 LocServiceTimesVector.pop_back();
18519 LocServiceTimesVector.push_back(TLSTEntry);
18524 LocServiceTimesVector.push_back(TLSTEntry);
18530 LocServiceTimesVector.push_back(TLSTEntry);
18549 LocServiceTimesVector.push_back(TLSTEntry);
18553 AnsiString TempDepTime = TLSTEntry.
DepTime;
18555 LocServiceTimesVector.push_back(TLSTEntry);
18557 while(TLSTEntry.
AtLocTime < TempDepTime)
18562 TLSTEntry.
DepTime = TempDepTime;
18563 LocServiceTimesVector.push_back(TLSTEntry);
18567 LocServiceTimesVector.push_back(TLSTEntry);
18578 LocServiceTimesVector.push_back(TLSTEntry);
18581 LocServiceTimesVector.push_back(TLSTEntry);
18598 AnsiString HString;
18599 AnsiString VString;
18602 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18606 HString = AnsiString(HLoc);
18610 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18614 VString = AnsiString(VLoc);
18616 TLSTEntry.
Location = HString +
'-' + VString;
18618 LocServiceTimesVector.push_back(TLSTEntry);
18623 AnsiString FrhTime;
18624 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18628 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18636 LocServiceTimesVector.push_back(TLSTEntry);
18642 LocServiceTimesVector.push_back(TLSTEntry);
18647 else if(AVE.
Command ==
"Frh-sh")
18649 if(y == NumTrains - 1)
18655 LocServiceTimesVector.push_back(TLSTEntry);
18661 LocServiceTimesVector.push_back(TLSTEntry);
18674 SequenceLog +=
"5\n";
18707 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18710 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18711 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18713 std::ofstream TTFile3(TTFileName3.c_str());
18717 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18721 if(LocServiceTimesVector.empty())
18723 ShowMessage(
"No timetabled services found");
18725 DeleteFile(TTFileName3);
18729 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18730 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18731 SequenceLog +=
"6\n";
18960 Ptr1 = LocServiceTimesVector.begin();
18962 while(Ptr2 != LocServiceTimesVector.end())
18964 while(Ptr2->Location == Ptr1->Location)
18967 if(Ptr2 == LocServiceTimesVector.end())
18974 if(Ptr2 != LocServiceTimesVector.end())
18982 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
18983 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18984 MinuteString =
" minutes";
18985 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18988 MinuteString =
" minute";
18990 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
18991 TTFile3 <<
",Platforms,Trains\n\n";
18993 Ptr1 = LocServiceTimesVector.begin();
18995 while(Ptr2 != LocServiceTimesVector.end())
18997 PreviousService =
"";
18998 NumTrainsAtLoc = 0;
18999 ServiceAndRepeatNumTotal =
"";
19001 NumPlatsAtThisLocCalculated =
false;
19003 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19005 PreviousService =
"";
19006 NumTrainsAtLoc = 0;
19007 ServiceAndRepeatNumTotal =
"";
19009 NumPlatsAtThisLocCalculated =
false;
19013 if(Ptr2 == LocServiceTimesVector.end())
19018 if(Ptr2 == LocServiceTimesVector.end())
19022 while(Ptr2->Location == Ptr1->Location)
19024 PreviousService =
"";
19025 NumTrainsAtLoc = 0;
19026 ServiceAndRepeatNumTotal =
"";
19027 BasicTime = Ptr1->ArrTime;
19028 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19032 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19034 BasicTime = Ptr2->ArrTime;
19037 if(Ptr2 == LocServiceTimesVector.end())
19041 if(Ptr2->Location != Ptr1->Location)
19046 if(Ptr2 == LocServiceTimesVector.end())
19050 if(Ptr2->Location != Ptr1->Location)
19056 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19060 if(!NumPlatsAtThisLocCalculated)
19063 NumPlatsAtThisLocCalculated =
true;
19065 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19067 if(ServiceAndRepeatNumTotal ==
"")
19069 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19070 NumTrainsAtLoc = 1;
19074 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19077 PreviousService = Ptr2->ServiceAndRepeatNum;
19078 if(ServiceAndRepeatNumTotal ==
"")
19080 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19081 NumTrainsAtLoc = 1;
19085 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19089 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19091 int MaxNumberOfSameDirections = 0;
19092 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19097 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19101 AnsiString Asterisk =
"";
19102 if(MaxNumberOfSameDirections >= NumPlats)
19107 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19108 ArrivalsPrinted =
true;
19109 ServiceAndRepeatNumTotal =
"";
19111 if(Ptr2 == LocServiceTimesVector.end())
19115 if(Ptr2->Location != Ptr1->Location)
19120 if(Ptr2 == LocServiceTimesVector.end())
19126 if(!ArrivalsPrinted)
19128 TTFile3 <<
"Nothing to report for arrivals";
19133 SequenceLog +=
"7\n";
19138 Ptr1 = LocServiceTimesVector.begin();
19140 while(Ptr2 != LocServiceTimesVector.end())
19142 while(Ptr2->Location == Ptr1->Location)
19145 if(Ptr2 == LocServiceTimesVector.end())
19152 if(Ptr2 != LocServiceTimesVector.end())
19159 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19160 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19161 MinuteString =
" minutes";
19162 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19165 MinuteString =
" minute";
19167 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19168 TTFile3 <<
",Platforms,Trains\n\n";
19170 Ptr1 = LocServiceTimesVector.begin();
19172 while(Ptr2 != LocServiceTimesVector.end())
19174 PreviousService =
"";
19175 NumTrainsAtLoc = 0;
19176 ServiceAndRepeatNumTotal =
"";
19178 NumPlatsAtThisLocCalculated =
false;
19180 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19182 PreviousService =
"";
19183 NumTrainsAtLoc = 0;
19184 ServiceAndRepeatNumTotal =
"";
19186 NumPlatsAtThisLocCalculated =
false;
19190 if(Ptr2 == LocServiceTimesVector.end())
19195 if(Ptr2 == LocServiceTimesVector.end())
19199 while(Ptr2->Location == Ptr1->Location)
19201 PreviousService =
"";
19202 NumTrainsAtLoc = 0;
19203 ServiceAndRepeatNumTotal =
"";
19204 BasicTime = Ptr1->DepTime;
19205 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19209 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19211 BasicTime = Ptr2->DepTime;
19214 if(Ptr2 == LocServiceTimesVector.end())
19218 if(Ptr2->Location != Ptr1->Location)
19223 if(Ptr2 == LocServiceTimesVector.end())
19227 if(Ptr2->Location != Ptr1->Location)
19233 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19237 if(!NumPlatsAtThisLocCalculated)
19240 NumPlatsAtThisLocCalculated =
true;
19242 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19244 if(ServiceAndRepeatNumTotal ==
"")
19246 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19247 NumTrainsAtLoc = 1;
19251 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19254 PreviousService = Ptr2->ServiceAndRepeatNum;
19255 if(ServiceAndRepeatNumTotal ==
"")
19257 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19258 NumTrainsAtLoc = 1;
19262 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19266 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19268 int MaxNumberOfSameDirections = 0;
19269 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19274 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19278 AnsiString Asterisk =
"";
19279 if(MaxNumberOfSameDirections >= NumPlats)
19284 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19285 DeparturesPrinted =
true;
19286 ServiceAndRepeatNumTotal =
"";
19288 if(Ptr2 == LocServiceTimesVector.end())
19292 if(Ptr2->Location != Ptr1->Location)
19297 if(Ptr2 == LocServiceTimesVector.end())
19303 if(!DeparturesPrinted)
19305 TTFile3 <<
"Nothing to report for departures";
19310 SequenceLog +=
"8\n";
19317 Ptr1 = LocServiceTimesVector.begin();
19319 while(Ptr2 != LocServiceTimesVector.end())
19321 while(Ptr2->Location == Ptr1->Location)
19324 if(Ptr2 == LocServiceTimesVector.end())
19331 if(Ptr2 != LocServiceTimesVector.end())
19338 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19339 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19340 TTFile3 <<
",Platforms,Trains,\n\n";
19341 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19342 Ptr1 = LocServiceTimesVector.begin();
19344 while(Ptr2 != LocServiceTimesVector.end())
19346 PreviousService =
"";
19347 ServiceAndRepeatNumTotal =
"";
19348 NumTrainsAtLoc = 0;
19350 NumPlatsAtThisLocCalculated =
false;
19353 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19355 PreviousService =
"";
19356 ServiceAndRepeatNumTotal =
"";
19357 NumTrainsAtLoc = 0;
19359 NumPlatsAtThisLocCalculated =
false;
19363 if(Ptr2 == LocServiceTimesVector.end())
19368 if(Ptr2 == LocServiceTimesVector.end())
19372 while(Ptr2->Location == Ptr1->Location)
19374 if(Ptr1->FrhMarker ==
"Frh")
19377 Ptr1->FrhMarker =
"FrhCounted";
19379 PreviousService =
"";
19380 NumTrainsAtLoc = 0;
19381 ServiceAndRepeatNumTotal =
"";
19382 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19386 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19389 if(Ptr1->FrhMarker ==
"Frh")
19392 Ptr1->FrhMarker =
"FrhCounted";
19395 if(Ptr2 == LocServiceTimesVector.end())
19399 if(Ptr2->Location != Ptr1->Location)
19404 if(Ptr2 == LocServiceTimesVector.end())
19408 if(Ptr2->Location != Ptr1->Location)
19412 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19414 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19418 if(!NumPlatsAtThisLocCalculated)
19421 NumPlatsAtThisLocCalculated =
true;
19423 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19425 if(ServiceAndRepeatNumTotal ==
"")
19427 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19428 NumTrainsAtLoc = 1;
19432 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19435 PreviousService = Ptr2->ServiceAndRepeatNum;
19436 if(ServiceAndRepeatNumTotal ==
"")
19438 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19439 NumTrainsAtLoc = 1;
19443 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19446 if(Ptr1->FrhMarker ==
"Frh")
19449 Ptr1->FrhMarker =
"FrhCounted";
19452 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19456 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19458 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19460 AnsiString Asterisk =
"";
19461 if(NumTrainsAtLoc > NumPlats)
19468 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19470 else if(FrhCount == 1)
19472 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19476 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19478 LastFrhCount = FrhCount;
19479 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19480 AtLocsPrinted =
true;
19481 ServiceAndRepeatNumTotal =
"";
19484 if(Ptr2 == LocServiceTimesVector.end())
19488 if(Ptr2->Location != Ptr1->Location)
19493 if(Ptr2 == LocServiceTimesVector.end())
19501 TTFile3 <<
"Nothing to report for trains at locations";
19506 SequenceLog +=
"9\n";
19540 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19545 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19554 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19556 SingleServiceEntry = TDE;
19558 for(
unsigned int y = 0; y < SSAV.size(); y++)
19560 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19562 SingleServiceVector.push_back(SingleServiceEntry);
19565 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19567 PartServiceEntry = TDE;
19569 for(
unsigned int z = 0; z <= y; z++)
19574 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19575 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19578 PartServiceVector.push_back(PartServiceEntry);
19579 if(SSAV.at(y).Command ==
"fsp")
19581 SSAV.at(y).Command =
"Front split - original service continues below";
19582 SSAV.at(y).OtherHeadCode =
"";
19584 if(SSAV.at(y).Command ==
"rsp")
19586 SSAV.at(y).Command =
"Rear split - original service continues below";
19587 SSAV.at(y).OtherHeadCode =
"";
19591 else if(SSAV.at(y).Command ==
"Fns")
19593 SSAV.at(y).Command =
"chr-Fns";
19594 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19595 PartServiceVector.push_back(SingleServiceEntry);
19598 else if(SSAV.at(y).Command ==
"Fns-sh")
19600 SSAV.at(y).Command =
"chr-Fns-sh";
19601 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19602 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19603 PartServiceVector.push_back(SingleServiceEntry);
19606 else if(SSAV.at(y).Command ==
"F-nshs")
19608 SSAV.at(y).Command =
"chr-F-nshs";
19609 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19610 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19611 PartServiceVector.push_back(SingleServiceEntry);
19617 SequenceLog +=
"10\n";
19621 AnsiString NextRef;
19622 while(!PartServiceVector.empty())
19624 PartServiceEntry = PartServiceVector.at(0);
19625 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19627 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19629 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19633 bool FinishType =
true, FoundFlag =
false;
19640 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19644 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19648 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19654 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19655 SingleServiceVector.push_back(PartServiceVector.at(0));
19656 PartServiceVector.erase(PartServiceVector.begin());
19661 NewPartServiceEntry = PartServiceVector.at(0);
19665 PartServiceVector.push_back(NewPartServiceEntry);
19668 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19673 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19676 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19678 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19681 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19683 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19686 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19689 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19690 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19691 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19692 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19695 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19699 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19700 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19701 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19709 SequenceLog += +
"11\n";
19710 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19714 if(!PartServiceVector.empty())
19716 SequenceLog +=
"12\n";
19717 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19719 SequenceLog +=
"13\n";
19766 bool BufferFacingUnReportedFlag =
true;
19767 bool TrainFacingBuffersReported =
false;
19768 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19774 SequenceLog +=
"13a\n";
19775 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19778 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19780 bool BufferFlag =
false;
19781 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19782 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19783 AnsiString FrontLocName = AV.at(0).LocationName;
19784 int NextEntryPos, NextExitPos;
19787 if(ThisElement.
Conn[0] == RearTVPos)
19791 else if(ThisElement.
Conn[1] == RearTVPos)
19795 else if(ThisElement.
Conn[2] == RearTVPos)
19799 else if(ThisElement.
Conn[3] == RearTVPos)
19811 if(ThisElement.
Conn[ThisExitPos] == -1)
19813 SequenceLog =
"13b\n";
19814 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19817 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19818 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19820 BufferFlag =
false;
19825 BufferFlag =
false;
19830 BufferFlag =
false;
19838 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19840 ThisElement = NextElement;
19846 if(NextEntryPos == 0)
19850 else if(NextEntryPos == 1)
19854 else if(NextEntryPos == 2)
19858 else if(NextEntryPos == 3)
19863 ThisElement = NextElement;
19864 ThisExitPos = NextExitPos;
19869 if(BufferFacingUnReportedFlag)
19871 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19872 BufferFacingUnReportedFlag =
false;
19874 if(AV.at(1).Command !=
"cdt")
19876 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
19877 TrainFacingBuffersReported =
true;
19882 if(!TrainFacingBuffersReported)
19884 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19890 SequenceLog +=
"13c\n";
19893 AnsiString LocationNameToBeChecked =
"";
19894 bool MissingcdtUnreportedFlag =
true;
19896 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19899 unsigned int y = 0;
19900 int FirstInstance = 9999, SecondInstance = 9999;
19901 bool FullBreak =
false;
19902 MarkerList.clear();
19904 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19913 LocationNameToBeChecked =
"";
19919 if(LocationNameToBeChecked ==
"")
19926 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19929 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19934 (AVEntry.
Command ==
"Frh-sh"))
19949 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19951 AnsiString LocationName;
19958 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
19963 LocationName = TDEntry.
ActionVector.at(a).LocationName;
19965 if(LocationName == LocationNameToBeChecked)
19967 SecondInstance = a;
19969 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19971 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19973 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19976 if(MissingcdtUnreportedFlag)
19978 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19980 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19981 MarkerList.push_back(FirstInstance);
19982 MarkerList.push_back(SecondInstance);
19984 MissingcdtUnreportedFlag =
false;
19995 if(MissingcdtUnreportedFlag)
19997 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20003 SequenceLog +=
"14\n";
20012 typedef std::list<AnsiString> TLocList;
20013 TLocList BackwardList, ForwardList;
20014 bool IntroLineNeeded =
true;
20015 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20017 unsigned int cdtPosition = 9999;
20018 AnsiString cdtLocation =
"";
20019 bool FoundSameName =
false;
20020 bool FerEntry =
false;
20021 MarkerList.clear();
20023 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
20030 BackwardList.clear();
20031 ForwardList.clear();
20032 bool ValidEnd =
false;
20038 (AVEntry.
Command ==
"Frh-sh"))
20043 if(FerEntry || ValidEnd)
20045 if(MarkerList.empty())
20052 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20054 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20056 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20060 if(IntroLineNeeded)
20062 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20063 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20064 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20065 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20066 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20067 IntroLineNeeded =
false;
20069 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20084 for(
int z = y - 1; z >= 0; z--)
20087 if(AVEntry2.
Command ==
"cdt")
20091 AnsiString LocName =
"";
20101 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
20103 BackwardList.push_back(LocName);
20106 BackwardList.sort();
20107 BackwardList.unique();
20108 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20117 AnsiString LocName =
"";
20118 if(AVEntry3.
Command ==
"Fer")
20120 int ExitLoc = AVEntry3.
ExitList.front();
20128 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
20130 ForwardList.push_back(LocName);
20133 ForwardList.sort();
20134 ForwardList.unique();
20135 FoundSameName =
false;
20137 if(!BackwardList.empty() && !ForwardList.empty())
20139 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20141 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20145 FoundSameName =
true;
20152 MarkerList.push_back(cdtPosition);
20157 if(IntroLineNeeded)
20159 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20177 SequenceLog +=
"15\n";
20183 catch(
const Exception &e)
20185 AnsiString TTErrorFileName =
"Analysis Error.txt";
20186 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20187 std::ofstream TTError(TTErrorFileName.c_str());
20190 ShowMessage(
"Analysis error file failed to open - can't be created");
20194 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20195 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20196 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20199 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20209 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20211 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20213 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20215 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20216 AnsiString Marker =
"";
20217 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20220 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20222 if(
int(x) == *MLIt)
20252 if(AVE.
Command.SubString(1,3) ==
"chr")
20261 AVE.
Command =
"Change of service to ";
20263 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20265 AVE.
Command =
"Change to shuttle finishing service";
20267 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20294 AnsiString ListOfExits =
"";
20303 VecFile << Marker <<
"Frh" <<
'\n';
20318 for(
unsigned int x = 0; x < Vector.size(); x++)
20321 if(Vector.at(x).ServiceReference == HeadCode)
20323 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20325 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20328 FinishType =
false;
20333 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20336 FinishType =
false;
20341 return(Vector.at(x));
20345 return(Vector.at(Vector.size() - 1));
20354 if((Time1 ==
"") || (Time2 ==
""))
20359 int Mins = Time1.SubString(4,2).ToInt();
20360 int Hours = Time1.SubString(1,2).ToInt();
20361 int Time1Mins = (Hours * 60) + Mins;
20362 Mins = Time2.SubString(4,2).ToInt();
20363 Hours = Time2.SubString(1,2).ToInt();
20364 int Time2Mins = (Hours * 60) + Mins;
20365 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20377 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20384 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20386 std::list<AnsiString> ServiceList;
20388 bool EvenComma =
false;
20389 for(
int x = 1; x <= Input.Length(); x++)
20391 TempStr1 = Input[x];
20392 if(TempStr1 == AnsiString(
',') && EvenComma)
20398 TempStr2 += Input[x];
20400 if(TempStr1 == AnsiString(
','))
20402 EvenComma = !EvenComma;
20406 while(TempStr2.Length() > 0)
20408 SCPos = TempStr2.Pos(
';');
20411 OneService = TempStr2.SubString(1, SCPos - 1);
20412 ServiceList.push_back(OneService);
20413 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20417 ServiceList.push_back(TempStr2);
20421 ServiceList.sort();
20422 ServiceList.unique();
20423 NumTrainsAtLoc = ServiceList.size();
20426 int DirectionMarker = 0;
20428 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20430 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20432 *SLIt = *SLIt +
"&0";
20434 SLIt3 = ServiceList.end();
20436 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20437 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20438 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20440 MaxNumberOfSameDirections = 0;
20441 int SameDirectionCount = 0;
20443 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20447 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20453 CommaPos1 = SLIt1->Pos(
',');
20454 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20456 SpacePos = ServiceRef1.Pos(
' ');
20460 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20461 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20462 if(RepeatInfo1[1] ==
'F')
20468 SpacePos = RepeatInfo1.Pos(
' ');
20469 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20472 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20474 AmpersandPos = AnsiTime1.Pos(
'&');
20475 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20480 throw Exception(
"ASCLIt1 Error in " + Input);
20482 ServiceCallingLocsList1 = ASCLIt1->second;
20483 AmpersandPos = SLIt1->Pos(
'&');
20484 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20485 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20487 SameDirectionCount = 1;
20488 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20490 CommaPos2 = SLIt2->Pos(
',');
20491 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20493 SpacePos = ServiceRef2.Pos(
' ');
20497 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20498 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20499 if(RepeatInfo2[1] ==
'F')
20505 SpacePos = RepeatInfo2.Pos(
' ');
20506 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20509 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20511 AmpersandPos = AnsiTime2.Pos(
'&');
20512 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20517 throw Exception(
"ASCLIt2 Error in " + Input);
20519 ServiceCallingLocsList2 = ASCLIt2->second;
20521 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20523 int AmpersandPos = SLIt2->Pos(
'&');
20524 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20525 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20526 SameDirectionCount++;
20529 if(SameDirectionCount > MaxNumberOfSameDirections)
20531 MaxNumberOfSameDirections = SameDirectionCount;
20536 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20539 AmpersandPos = SLIt3->Pos(
'&');
20540 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20541 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20544 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20547 AmpersandPos = SLIt->Pos(
'&');
20548 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20549 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20550 DirectionMarker = DirectionMarkerString.ToInt();
20551 AnsiString DirectionSuffix =
"";
20553 if(DirectionMarker < 27)
20555 c = 64 + DirectionMarker;
20556 DirectionSuffix =
"," + AnsiString(c);
20558 else if(DirectionMarker < 53)
20560 c = 65 + DirectionMarker - 27;
20561 DirectionSuffix =
",A" + AnsiString(c);
20565 DirectionSuffix =
",?";
20567 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20570 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20572 Output = Output + *SLIt +
",";
20574 if(Output.Length() > 0)
20576 Output = Output.SubString(1, Output.Length() - 1);
20582 catch(
const Exception &e)
20584 AnalysisError =
true;
20596 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20598 std::list<AnsiString> ServiceList;
20600 while(InternalInput.Length() > 0)
20602 CommaPos = InternalInput.Pos(
',');
20605 OneService = InternalInput.SubString(1, CommaPos - 1);
20606 ServiceList.push_back(OneService);
20607 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20611 ServiceList.push_back(InternalInput);
20612 InternalInput =
"";
20616 ServiceList.sort();
20617 ServiceList.unique();
20618 NumTrainsAtLoc = ServiceList.size();
20619 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20621 Output = Output + *SLIt +
",";
20623 if(Output.Length() > 0)
20625 Output = Output.SubString(1, Output.Length() - 1);
20638 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20640 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20645 bool LocFound =
false;
20646 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20648 TDateTime FirstServiceTime;
20651 int Ref1Target = 0, Ref1Count = 0;
20652 int Ref2Target = 0, Ref2Count = 0;
20670 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20673 if((*ListPtr1) == Location)
20675 LocPtr1 = ListPtr1;
20678 if(ListPtr1->SubString(1, 3) ==
"%%%")
20680 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20685 FirstServiceTime = TDateTime(-1);
20686 bool BreakFlag =
false;
20689 if(TDVIt->ServiceReference == Ref1)
20691 if(Ref1Target > Ref1Count)
20696 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20697 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20701 FirstServiceTime = AVIt->EventTime;
20707 FirstServiceTime = AVIt->ArrivalTime;
20713 FirstServiceTime = AVIt->DepartureTime;
20724 if(IncMinutes == -1)
20726 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20728 if(FirstServiceTime == TDateTime(-1))
20730 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20734 if(!Arrival && (Time1 == CDTTime))
20739 if(Arrival && (Time1 == CDTTime))
20743 if(Time1 > CDTTime)
20748 if(Time1 < CDTTime)
20761 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20763 if((*ListPtr2) == Location)
20765 LocPtr2 = ListPtr2;
20768 if(ListPtr2->SubString(1, 3) ==
"%%%")
20770 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20775 FirstServiceTime = TDateTime(-1);
20776 bool BreakFlag =
false;
20779 if(TDVIt->ServiceReference == Ref2)
20781 if(Ref2Target > Ref2Count)
20786 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20787 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20791 FirstServiceTime = AVIt->EventTime;
20797 FirstServiceTime = AVIt->ArrivalTime;
20803 FirstServiceTime = AVIt->DepartureTime;
20814 if(IncMinutes == -1)
20816 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20818 if(FirstServiceTime == TDateTime(-1))
20820 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20824 if(!Arrival && (Time2 == CDTTime))
20829 if(Arrival && (Time2 == CDTTime))
20833 if(Time2 > CDTTime)
20838 if(Time2 < CDTTime)
20853 LP1 = List1.begin();
20855 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20857 if(ListPtr1 == List1.begin())
20861 if(ListPtr1->SubString(1, 3) ==
"%%%")
20868 LP2 = List2.begin();
20870 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20872 if(ListPtr2 == List2.begin())
20876 if(ListPtr2->SubString(1, 3) ==
"%%%")
20886 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20888 if(ListPtr1 == LocPtr1)
20892 if(ListPtr1->SubString(1, 3) ==
"%%%")
20896 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20898 if(ListPtr2 == LocPtr2)
20902 if(ListPtr2->SubString(1, 3) ==
"%%%")
20906 if((*ListPtr1) == (*ListPtr2))
20923 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20925 if(ListPtr1 == List1.end())
20929 if(ListPtr1->SubString(1, 3) ==
"%%%")
20933 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20935 if(ListPtr2 == List2.end())
20939 if(ListPtr2->SubString(1, 3) ==
"%%%")
20943 if((*ListPtr1) == (*ListPtr2))
20960 if(ExitList.empty())
20966 AnsiString ExitLocList =
"";
20969 unsigned int Counter = 0;
20970 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20974 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20976 ExitLocList +=
"\n";
20979 if(StartName ==
"")
20981 if(ExitList.size() == 1)
20985 return(
" at " + ID);
20990 if(ExitList.size() < 4)
20992 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20997 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21002 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21007 if(ExitList.size() < 4)
21009 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21014 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21020 if(ExitList.size() < 4)
21022 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21023 return(
" at " + StartName);
21027 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21028 return(
" at " + StartName);
21068 AnsiString FormatStr =
"####0.0";
21069 AnsiString AvLateArrMins =
"";
21070 AnsiString AvEarlyArrMins =
"";
21071 AnsiString AvLatePassMins =
"";
21072 AnsiString AvEarlyPassMins =
"";
21073 AnsiString AvLateDepMins =
"";
21074 AnsiString AvLateExitMins =
"";
21075 AnsiString AvEarlyExitMins =
"";
21078 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21111 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21112 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21124 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21128 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21136 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21140 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21148 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21156 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21160 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21164 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21168 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21172 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21176 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21181 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21185 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21189 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21193 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21197 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21201 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21205 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21209 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21214 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21218 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21222 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21226 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21230 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21232 TDateTime TempExcessLCDownTime;
21246 if(TempExcessLCDownTime > TDateTime(0))
21252 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21256 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21268 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21272 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21308 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21312 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21318 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21322 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21325 AnsiString AvLateMinsLocsNotReached =
"";
21331 if(LocsNotReached > 0)
21334 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21338 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21342 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21354 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21358 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21368 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21370 bool DerailSPADFlag =
false, CrashFlag =
false;
21372 int OverallScorePercent = 100;
21373 int TotArrDepExit = 0;
21374 double TotLateMinsFactor = 1;
21375 double MissedStopAndSPADRiskFactor = 1;
21376 double NetNegFactor = 1;
21386 OverallScorePercent = 5;
21387 DerailSPADFlag =
true;
21391 OverallScorePercent = 0;
21394 if(OverallScorePercent == 100)
21399 LatenessPenalty = 0;
21405 if(TotArrDepExit > 0)
21414 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21416 OverallScorePercent = 100 * NetNegFactor;
21419 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21422 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21423 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21424 AnsiString AddedString =
"";
21427 AddedString = OneFailureString;
21431 AddedString = TwoOrMoreFailureString;
21433 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21434 AnsiString Rating =
"";
21435 if(OverallScorePercent == 100)
21437 Rating =
"Perfect!";
21439 else if(OverallScorePercent >= 95)
21441 Rating =
"Excellent";
21443 else if(OverallScorePercent >= 90)
21445 Rating =
"Very good";
21447 else if(OverallScorePercent >= 80)
21451 else if(OverallScorePercent >= 70)
21455 else if(OverallScorePercent >= 60)
21457 Rating =
"Unacceptable" + AddedString;
21459 else if(OverallScorePercent >= 50)
21461 Rating =
"Poor" + AddedString;
21463 else if(OverallScorePercent >= 40)
21465 Rating =
"Bad" + AddedString;
21467 else if(OverallScorePercent >= 30)
21469 Rating =
"Very bad" + AddedString;
21471 else if(OverallScorePercent >= 20)
21473 Rating =
"Terrible" + AddedString;
21475 else if(OverallScorePercent >= 10)
21477 Rating =
"Appalling" + AddedString;
21479 else if(OverallScorePercent >= 5)
21483 Rating =
"Disastrous - potential loss of life";
21488 Rating =
"Dire" + AddedString;
21491 else if(OverallScorePercent < 5)
21495 Rating =
"Catastrophic - loss of life";
21499 Rating =
"Abysmal";
21502 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21506 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21508 PerfFile <<
'\n' <<
"***************************************";
21518 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21568 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21603 int IncrementalMinutes = 0;
21617 bool TrainOperatingFlag =
false;
21622 TrainOperatingFlag =
true;
21626 if(TrainOperatingFlag)
21634 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21681 AnsiString HeadCode;
21685 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21689 HCandTrainPosParam.first = HeadCode;
21690 HCandTrainPosParam.second = TrainID;
21692 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21695 OpTimeToActMultiMapEntry.first = TimeToAct;
21696 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21725 float TimeToAct = 0;
21726 int DistanceToRedSignal = 0;
21729 ContinuationEntryVecPosVector.clear();
21730 bool LaterTrain =
false;
21734 LaterTrain =
false;
21735 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21746 if(!ContinuationEntryVecPosVector.empty())
21748 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21750 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21764 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21765 AnsiString HeadCode = CTEIt->second.HeadCode;
21766 float CurrentStopTime;
21767 float LaterStopTime;
21768 float RecoverableTime;
21771 int DistanceToExit;
21773 bool SigControlAndCanPassRedSignal =
false;
21781 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21787 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21788 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21791 if(AvTrackSpeed < 30)
21795 if(DistanceToRedSignal == -1)
21801 int Speed = AvTrackSpeed;
21802 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21803 if(AvTrackSpeed > MaxSpeed)
21807 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21810 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21813 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21818 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21819 TimeToAct += MinsBefEnter;
21822 HCandTrainPosParam.first = HeadCode;
21823 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21826 if(TimeToAct < 59.9)
21828 OpTimeToActMultiMapEntry.first = TimeToAct;
21829 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21854 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21864 TimeToExitMultiMapEntry.first = ExitPair;
21865 TimeToExitMultiMapEntry.second = ExitInfo;
21875 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21876 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21885 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21886 int DistanceToRedSignal = 0;
21887 DistanceToExit = -1;
21888 ExitPair.first = -1;
21889 ExitPair.second = -1;
21890 int CumTrackSpeed = 0;
21892 int TrackSpeedCount = 0;
21893 float KmPerLocationStop;
21894 float MaxAllowableSpeed;
21904 int CurrentElement = TrackVectorPosition;
21905 int CurrentEntryPos = TrackVectorPositionEntryPos;
21910 CurrentStopTime = 0;
21912 RecoverableTime = 0;
21913 if(CurrentElement == -1)
21918 int CurrentExitPos;
21923 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21927 CurrentExitPos = 1;
21931 CurrentExitPos = 3;
21936 CurrentExitPos = 0;
21975 TimeToDepart+= 0.5;
21977 if(TimeToDepart < 0.5)
21979 TimeToDepart = 0.5;
21982 CurrentStopTime = float(TimeToDepart);
21990 CurrentStopTime = float(TimeToDepart);
22001 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22012 else if(SigControlAndCanPassRedSignal)
22017 if((NextEntryPos == 0) || (NextEntryPos == 2))
22038 CurrentElement = NextElement;
22039 CurrentEntryPos = NextEntryPos;
22040 CurrentExitPos = NextExitPos;
22052 int LaterStopNumber = 0;
22056 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22065 if(CurrentEntryPos > 1)
22080 DistanceToExit = DistanceToRedSignal;
22085 if(TrackSpeedCount > 0)
22087 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22091 if(CurrentEntryPos > 1)
22102 if(LaterStopNumber > 0)
22104 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22105 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22111 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22115 if(AvTrackSpeed > MaxAllowableSpeed)
22117 AvTrackSpeed = MaxAllowableSpeed;
22129 bool StopRequired =
false;
22148 int TrainOnElement;
22155 if(CurrentEntryPos > 1)
22164 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22173 double StopTimeDouble;
22186 if(StopTimeDouble < 0.5)
22188 StopTimeDouble = 0.5;
22192 LaterStopTime += float(StopTimeDouble);
22193 RecoverableTime += StopTimeDouble - 0.5;
22194 if((LaterStopNumber == 1) && (TrainID > -1))
22202 if((AVPtr + 1)->FormatType ==
TimeLoc)
22206 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22217 if(StopTimeDouble < 0.5)
22219 StopTimeDouble = 0.5;
22222 LaterStopTime += float(StopTimeDouble);
22223 RecoverableTime += StopTimeDouble - 0.5;
22224 if((LaterStopNumber == 1) && (TrainID > -1))
22234 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22245 if(StopTimeDouble < 0.5)
22247 StopTimeDouble = 0.5;
22250 LaterStopTime += float(StopTimeDouble);
22251 RecoverableTime += StopTimeDouble - 0.5;
22252 if((LaterStopNumber == 1) && (TrainID > -1))
22269 if(NextElement == -1)
22278 if((NextEntryPos == 0) || (NextEntryPos == 2))
22299 CurrentElement = NextElement;
22300 CurrentEntryPos = NextEntryPos;
22301 CurrentExitPos = NextExitPos;
22306 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22319 if(TrackSpeedCount > 0)
22321 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22325 if(CurrentEntryPos > 1)
22336 if(LaterStopNumber > 0)
22338 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22339 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22345 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22349 if(AvTrackSpeed > MaxAllowableSpeed)
22351 AvTrackSpeed = MaxAllowableSpeed;
22354 return(DistanceToRedSignal);